Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

제안 - 아희 2015 #8

Open
youknowone opened this issue Mar 31, 2015 · 32 comments
Open

제안 - 아희 2015 #8

youknowone opened this issue Mar 31, 2015 · 32 comments

Comments

@youknowone
Copy link
Member

제안: 아희2015

아희의 표준을 보다 명확하게 정리하고 창제 원리에 맞게 기능 추가 및 미정의 부분 보완을 제안합니다. 아희의 원 표준은 http://aheui.github.io/specification.ko/ 를 참고해 주세요.

#제안-보완으로 표시된 부분은 기존의 표준에서 정의되지 않았던 부분입니다. #제안-추가는 기존의 표준과 달라지는 부분입니다. 아무 것도 표시되지 않은 부분은 기존의 표준과 동일한 내용을 재정의한 부분입니다.

개요

인터프리터가 아희를 실행하는 방법은 befunge와 비슷합니다. 즉, 코드 공간 안에 커서가 있어서 커서가 위치한 곳에 적혀 있는 명령을 수행하고, 또 그 명령에 따라 커서가 움직이는 것입니다. 하지만, 그 코드가 ASCII가 아니라 한글이라는 점이 다릅니다.

한글은 홀소리와 닿소리로 나눌 수 있습니다. 홀소리는 커서가 이동할 방향을 지정하고, 닿소리는 인터프리터가 수행할 명령을 지정합니다. 받침이 있는 글자는 닿소리가 두 개가 되는데, 이 때 받침은 명령을 보조하는 인자로 작용합니다.

아희에서 쓰이는 저장 공간은 여러 개가 있습니다. 대부분이 스택이고, 큐가 하나 있습니다. 그리고 확장기능과 소통하는 통로가 있는데 2015표준에서는 정의하지 않습니다. 집어넣기(push)로 인수를 전달하고 뽑아내기(pop)로 결과를 받아옵니다.

코드

  • 아희의 코드는 UTF-8로 표현된 유니코드 문자로만 이루어진 텍스트입니다.
  • 아희의 코드에는 어떤 utf-8 문자도 올 수 있으나, 프로그램의 진행에는 오직 유니코드 한글 낱자 영역(16진수 코드 포인트 AC00-D7A3, hangul syllable 영역)의 문자만 영향을 끼칩니다.
    • 완전하지 않은 낱자인 ㄱ, ㄷ, ㅑ, ㅓ 등은 무시합니다. 이런 기능을 사용하고 싶다면 기능이 없는 닿소리나 기능이 없는 홀소리를 조합해 쓸 수 있습니다.
    • 첫가끝 코드 등의 다른 방식으로 표현된 한글도 무시합니다.
  • 아희의 코드는 줄바꿈에 민감합니다. 줄바꿈 문자는 Line feed 문자인 유니코드 0A 또는 흔히 '\n'로 가리키는 문자를 사용합니다. 단 그 앞에 Carriage return 문자인 유니코드 0D 또느 흔히 '\r'로 가리키는 문자가 있는 경우 두 문자를 합쳐서 줄바꿈으로 다룹니다. (#제안-보완)
  • 코드는 닿소리부터 실행하고 홀소리에 따라서 움직입니다. 하지만 닿소리가 홀소리의 동작을 재정의할 경우에는 진행방향을 먼저 결정한 후, 실제로 이동하기는 전에 재정의가 이루어집니다.
    1. 닿소리를 먼저 실행합니다. 이때 진행방향 재정의가 있다면 재정의를 예약합니다.
    2. 홀소리에 따라 이동 방향을 결정합니다.
    3. 예약된 진행방향 재정의가 있다면 이동 방향을 변경합니다.
    4. 이동 방향에 따라 이동합니다.

커서 - 홀소리

  • 아희는 코드를 매 유니코드 문자 하나를 격자 단위로 하는 평면으로 해석합니다.
  • 커서를 옮기는 데는 한글 문자의 홀소리에만 영향을 받습니다. 각 홀소리의 동작은 아래의 정리를 참고합니다.
  • 커서의 진행에는 관성이 있습니다. 홀소리가 아무 일도 하지 않으면 이전의 이동 방향과 크기를 유지하려는 성질이 있습니다.
  • 프로그램이 시작할 때 커서는 1행 1열에 있고 아래 방향으로 한 칸 진행하려는 상태입니다.
    • 이는 가상의 0행 1열에 '우' 문자가 있어 아래로 한 칸 이동해 온 것과 같은 상태로 해석할 수 있습니다.
    • 이는 기본 방향이 오른쪽인 funge와는 다른 점입니다. 이렇게 함으로서 코드 맨 윗줄에 #!을 추가로 넣더라도 문제없이 동작할 수 있습니다.
  • 커서가 코드 공간의 한 쪽 끝에 다다르면 커서는 반대편 끝으로 이동합니다.
    • 반대편 끝은 코드 텍스트에서 진행방향 반대편에 존재하는 첫 문자를 가리킵니다. 첫 문자는 줄바꿈 문자를 제외한 어떤 문자도 될 수 있습니다. (#제안-추가)
      • 진행 방향이 오른쪽인 경우 진행 방향의 끝은 그 행의 마지막 문자이고 반대편 끝은 그 행의 첫 문자입니다.
      • 진행 방향이 왼쪽인 경우 진행 방향은 그 행의 첫 문자이고 반대편 끝은 그 행의 마지막 문자입니다.
      • 진행 방향이 아래인 경우 진행 방향의 끝은 그 열에서 가장 마지막으로 나타나는 줄이고 반대편 끝은 첫 줄입니다.
      • 진행 방향이 위인 경우 진행 방향의 끝은 첫 줄이고 반대편 끝은 그 열에서 가장 마지막으로 나타나는 줄입니다.
      • 진행 방향이 오른쪽 위인 경우 진행 방향의 끝은 첫 줄이고 반대편 끝은 출발점에서 진행 방향의 끝까지 그은 연장선 중 첫 열을 지나는 점입니다.
      • 진행 방향이 왼쪽 아래인 경우 진행 방향의 끝은 첫 열이고 반대편 끝은 출발점에서 진행 방향의 끝까지 그은 연장선 중 첫 행을 지나는 점입니다.
      • 코드 공간 사이에 코드가 없는 빈 공간은 한글 영역 밖의 임의의 문자로 간주하여 관성에 따라서만 움직입니다.
    • 한 번에 두 칸씩 이동하는 홀소리를 만나면 먼저 두 칸을 이동한 뒤 코드 공간의 끝임을 확인하고 반대편 끝으로 이동합니다. 즉 코드 공간의 끝에서 두 칸을 이동하더라도 반드시 반대편 끝으로 도착합니다. (#제안-보완)
  • 연산에 필요한 충분한 갯수의 값이 저장공간에 저장되어 있지 않은 경우, 커서는 그 명령을 실행하지 않고 진행해야 할 방향의 반대방향으로 같은 크기만큼 움직입니다. (#제안-보완)
    • 종료만 제외하고, 중복과 바꿔치기 명령을 포함한 모든 뽑아내기를 쓰는 명령에 해당합니다.
  • 따라서 각 이동성분 속력의 합은 최소 1, 최대 2입니다. 커서는 정지하거나 두 칸을 초과하는 속도로 이동할 수 없습니다.

각 홀소리의 기능은 다음과 같습니다.

  • ㅏ, ㅓ, ㅗ, ㅜ: 커서를 각각 오른쪽, 왼쪽, 위, 아래로 한 칸 옮깁니다.
  • ㅑ, ㅕ, ㅛ, ㅠ: 커서를 각각 오른쪽, 왼쪽, 위, 아래로 두 칸 옮깁니다.
  • ㅡ: 커서의 가로 이동 성분은 유지하고, 세로 이동 성분은 반대로 뒤집어 이동합니다.
  • ㅣ: 커서의 세로 이동 성분은 유지하고, 가로 이동 성분은 반대로 뒤집어 이동합니다.
  • ㅢ: 커서의 진행 방향을 뒤집어 이동합니다.
  • ㅘ - 오른쪽으로 한칸 이동 후 위로 한칸 옮깁니다. 커서 관성은 오른쪽과 위쪽 이동이 모두 보존됩니다. 첫 이동 후 코드 공간 끝에 다다를 경우 먼저 반대편 끝으로 이동 후 다음 이동을 합니다. (#제안-추가)
  • ㅝ - 왼쪽으로 한칸 이동 후 아래로 한칸 옮깁니다. 커서 관성은 왼쪽과 아래쪽 이동이 모두 보존됩니다. 첫 이동 후 코드 공간 끝에 다다를 경우 먼저 반대편 끝으로 이동 후 다음 이동을 합니다. (#제안-추가)
  • ㅚ - 커서의 세로 이동을 ㅗ와 같이 바꾸고, 가로 이동 성분에 대해서는 ㅣ와 같이 반대로 뒤집어 이동하되 원래 두 칸이라면 한 칸만 이동합니다. (#제안-추가)
  • ㅟ - 커서의 세로 이동을 ㅜ와 같이 바꾸고, 가로 이동 성분에 대해서는 ㅣ와 같이 반대로 뒤집어 이동하되 원래 두 칸이라면 한 칸만 이동합니다. (#제안-추가)
  • 기능 없음: ㅐ ㅔ ㅒ ㅖ ㅙ ㅞ (#제안-추가)

명령어 - 닿소리

각 닿소리의 기능은 다음과 같습니다.

ㅇ 묶음 - 받침은 모두 무시합니다.

  • ㅇ은 없음 명령으로 아무 일도 하지 않습니다.
  • ㅎ은 끝냄 명령으로 커서의 실행을 끝냅니다. 이 때 현재 선택된 저장 공간에 값이 하나 이상 남아 있으면 ㅁ 명령으로 뽑아낼 수 있는 값을 뽑아내 운영체제에 돌려 줍니다. 저장 공간이 비어 있으면 0을 돌려줍니다.
    • 저장 공간이 비어 있더라도 커서의 실행은 끝냅니다. 반대 방향으로 이동하지 않습니다.

ㄷ 묶음 - 셈. 받침은 모두 무시합니다.

  • ㄷ은 덧셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 둘을 더한 값을 저장공간에 집어넣습니다.
  • ㄸ은 곱셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 둘을 곱한 값을 저장공간에 집어넣습니다.
  • ㅌ은 뺄셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 나중 값에서 먼저 값을 뺀 값을 저장공간에 집어넣습니다.
  • ㄴ은 나눗셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 나중 값에서 먼저 값을 나눈 값을 저장공간에 집어넣습니다.
  • ㄹ은 나머지 명령으로 저장공간에서 두 값을 뽑아낸 다음 나중 값에서 먼저 값을 나눈 나머지를 저장공간에 집어넣습니다.

ㅁ 묶음 - 저장공간

  • ㅁ은 뽑기 명령입니다. 지금 저장공간이 스택이라면 맨 위의 값, 큐라면 맨 앞의 값을 뽑아냅니다.(pop)
    • ㅇ 받침이 오면 뽑아낸 값을 표준 출력에 음수의 경우 부호 -를 포함해 0-9 사이의 문자만을 사용해 10진수로 출력합니다.
    • ㅎ 받침이 오면 표준 출력에 뽑아낸 값에 해당하는 코드포인트의 유니코드 문자를 utf-8로 출력합니다.
    • ㅎ 받침에서 유니코드 코드 포인트가 아닌 값을 출력하려 하면 저장공간에서 값을 뽑지 않은 채 진행 방향을 반대로 바꿉니다. (#제안-추가)
    • 다른 받침이 오면 뽑아낸 값을 버립니다.
  • ㅂ은 집어넣기 명령입니다. 지금 저장공간이 스택이라면 맨 위에, 큐라면 맨 뒤에 값을 집어넣습니다.(push)
    • ㅇ 받침이 오면 표준 입력에서 정수 문자열을 받아 이에 해당하는 값을 지금 저장공간에 집어넣습니다.
    • ㅎ 받침이 오면 표준 입력에서 utf-8로 유니코드 문자를 받아 이에 해당하는 유니코드 코드포인트를 지금 저장공간에 집어넣습니다.
    • ㅎ 받침이 왔지만 utf-8로 해석할 수 없는 문자가 입력될 경우 1바이트를 소비하고 진행방향을 뒤집습니다. (#제안-보완)
    • ㅇ이나 ㅎ이 아닌 받침에 대해서는 각각 상수를 저장공간에 집어넣습니다. 그 상수 값은 아래의 표를 참고합니다.
    • ㅇ에서 입력할 수 있는 숫자는 음수 부호 -가 첫 자리에 올 수 있는 0-9 사이의 숫자로만 이루어진 10진수입니다. (#제안-보완)
    • ㅇ에서 숫자가 아닌 문자를 받을 경우 16진수 코드포인트 09('\t'), 0A('\n'), 0D('\r'), 20(' ')에 해당하는 문자라면 소비시키고, 다른 문자라면 다음 입력에 쓸 수 있도록 보존합니다. 단 0D('\r')와 0A('\n')가 연달아 나타나면 둘 모두 소비시킵니다. (#제안-보완)
    • ㅇ이나 ㅎ에서 EOF를 만나 더이상 입력을 받을 수 없는 경우 진행 방향을 뒤집습니다. (#제안-추가)
  • ㅃ은 중복 명령입니다. 지금 저장공간이 스택이라면 맨 위의 값을 그 값 위에 하나 더 집어넣고, 큐라면 맨 앞의 값을 앞에 하나 더 덧붙입니다.
  • ㅍ은 바꿔치기 명령입니다. 지금 저장공간이 스택이라면 맨 위 값과 그 바로 아래 값을, 큐라면 맨 앞의 값과 그 바로 뒤 값을 바꿉니다.

ㅂ의 경우 ㅇ, ㅎ 외의 나머지 받침이 있으면 그 받침을 구성하는 직선의 수와 원의 수의 합에 따른 값을 집어넣습니다. 받침이 없으면 0을 집어넣습니다.

2 2 3 5 4 4 2 3 4 3 4 4
4 4 5 5 7 9 9 7 9 9 8 6 4

받침 중에는 1획인 것이 없는데, 1은 2/2나 3-2 같은 셈으로 간단하게 만들 수 있습니다. 예: 반밧나, 밪반타 등.

ㅅ 묶음 - 제어, 저장공간 확장

  • ㅅ은 선택 명령으로 저장공간을 선택합니다. 어느 것을 선택하는지는 받침을 따르는데, 이에 대한 설명은 아래를 참고하세요.
  • ㅆ은 이동 명령으로 지금의 저장공간에서 값 하나를 뽑아내 받침이 나타내는 저장공간에 그 값을 집어 넣습니다.
  • ㅈ은 비교 명령으로 저장공간에서 값 두 개를 뽑아 내서 비교합니다. 나중에 뽑아낸 값이 더 크거나 같으면 1을, 아니면 0을 지금 저장공간에 집어넣습니다.
  • ㅊ은 조건 명령으로 저장공간에서 값 하나를 뽑아내서 그 값이 0이 아니면 진행해야 할 방향대로, 0이면 그 반대 방향으로 갑니다.

저장공간

  • 아희에는 총 28개의 저장공간이 있습니다.
  • 저장공간은 스택, 큐, 통로 세 가지 종류가 있습니다.
  • 스택이 26개, 큐가 1개, 통로가 1개 이며 각각의 저장공간에는 이름이 붙어 있어 그 중 스택은 (받침 없음), ㄱ, ㄴ, ㄷ, ㄹ, ㅁ, ㅂ, ㅅ, ㅈ, ㅊ, ㅋ, ㅌ, ㅍ, ㄲ, ㄳ, ㄵ, ㄶ, ㄺ, ㄻ, ㄼ, ㄽ, ㄾ, ㄿ, ㅀ, ㅄ, ㅆ가 있고, ㅇ은 큐이며, ㅎ은 확장 기능과 소통하기 위한 통로입니다.
  • 각 저장공간은 ㅅ나 ㅆ 명령에서 받침으로 선택할 수 있습니다.
  • 처음에 선택되어 있는 저장공간은 (받침 없음) 스택입니다.
    • (“사” 와 같은 명령으로 다시 선택할 수 있습니다.)
  • 저장공간에는 정수만 담을 수 있으며 정수는 부호를 지원합니다. (#제안-보완)
  • 저장공간은 최소한 32비트의 부호 있는 정수를 지원해야합니다. (#제안-보완)
    • 구현체에 따라 그 이상의 큰 정수를 지원할 수 있습니다.
  • 저장공간에 넣을 수 있는 값의 수는 무한합니다. (#제안-보완)

예제

다음은 “Hello, world!”를 출력하는 프로그램입니다.

밤밣따빠밣밟따뿌
빠맣파빨받밤뚜뭏
돋밬탕빠맣붏두붇
볻뫃박발뚷투뭏붖
뫃도뫃희멓뭏뭏붘
뫃봌토범더벌뿌뚜
뽑뽀멓멓더벓뻐뚠
뽀덩벐멓뻐덕더벅

더 많은 코드는 github.com/aheui/snippets를 참고하세요.

@puzzlet
Copy link
Member

puzzlet commented Apr 2, 2015

아희에도 마찬가지 문제가 있는데, '반대편 끝'이 어디인지가 명확하지 않습니다. 예를 들어, 다음 코드를 실행하면 0이 나와야 할까요 00이 나와야 할까요? 코딩하는 사람은 00이 나올 것을 기대하고 쓸 것 같은데, caheui 지금 버전에서는 바로 윗칸을 '반대편 끝'으로 간주하기 때문에 0이 나올 겁니다.

여희망어버버
일이삼사오륙칠팔구

@youknowone
Copy link
Member Author

그러네요. 반대편 끝의 정의에 따라 두 칸씩 이동하는 경우에 문제가 생기네요. 제 생각엔 반대편 끝은 반드시 다음 글자가 나오는 첫 자리(오른쪽 버)여야 직관적이고 다른 행의 크기에 영향도 받지 않게 될 것 같습니다. 줄끝문자 정의도 다시 할 필요가 있어 보이는데, \n만 정의해도 \r이 저절로 무시되지 않나 싶었는데 지금 같은 경우면 안그렇겠네요.

@lifthrasiir
Copy link
Member

"한 번에 두 칸씩 이동하는 홀소리를 만나면 먼저 두 칸을 이동한 뒤 코드 공간의 끝임을 확인하고 반대편 끝으로 이동합니다."가 정식으로 채택될 경우 Funge-98 wrapping algorithm에 대한 언급은 삭제되어야 합니다. (이 알고리즘의 기본 가정은, 어느 방향으로 얼마만큼 움직이든 다른 명령이나 방향 변경이 없을 경우 한 바퀴 돌고 와서 항상 처음 시작했던 장소로 돌아와야 한다는 것입니다.)

@disjukr
Copy link
Member

disjukr commented Apr 2, 2015

@youknowone
첫 행의 가로 반대편 끝을 마지막 로 취급한다면, 지금 구현체들의 세로이동과 일관성이 사라지지 않을까요?

아요
희어
ㅋ

위의 케이스에서는 무한히 명령이 반복되는 게 맞을까요, 프로그램이 끝나는 게 맞을까요?


줄끝문자는 /\r?\n/으로 하나처럼 묶어서 처리하는게 좋지 않을까요?

@youknowone
Copy link
Member Author

이 정의에 따르면 "요" 에서 두 칸을 이동하면 코드 공간 끝을 만나고 반대편 끝이 "어"이므로 멈추게 되겠지요. 줄끝은 두 칸 이동을 고려하면 그렇게 처리하는게 맞을거 같습니다.

@youknowone
Copy link
Member Author

댓글로 나온 내용 수정해 반영해 보았습니다. 제가 이해하는 아희에 대한 인식을 바탕으로 한 제안이니, 다른 분들 인식과 조금 다른 가정을 하고 정해진 부분도 있을 수 있습니다. 가능하면 널리 받아들여질 수 있는 방법으로 제안하고 싶으니 많은 의견을 부탁드립니다. (ㄱ 계열의 파일 입출력 확장 같은 것도 들어있었는데, 공감을 얻기 어렵겠다 싶어 일단 뺀 상태입니다)

코드 공간의 정의에 관해서는 이전에 비해 세세히 엄밀하게 따지게 되었는데, 아무래도 ㅘ, ㅝ의 추가 때문에 경계가 명확하지 않으면 이 두 모음의 동작은 정말로 예측할수가 없게 됩니다. ㅑ, ㅕ 동작과 충돌하지 않으면서도 확실한 정의를 할 수 있으면 좋겠습니다.

호환성에 관해서는 이전 표준의 불분명한 부분으로 인해 초래된 부분을 완벽하게 극복할 수는 없다고 생각합니다. 다만 구현체들이 널리 받아들인 사실상의 표준(예: ㅎ 명령은 스택이 비어있어도 반대 방향으로 이동하지 않음)과는 충돌하지 않도록 꼭 조절할 수 있으면 합니다.

@disjukr
Copy link
Member

disjukr commented Apr 2, 2015

@youknowone 묶음 에 줄바꿈 문자 업데이트 안된 것 같아요.

@youknowone
Copy link
Member Author

고치긴 했는데 잘하는 짓인지 모르겠네요. utf-8도 강요하는 마당에 '\r'도 지원 안해도 그만일거 같기도 한데 말이에요.

@disjukr
Copy link
Member

disjukr commented Apr 2, 2015

우어
ㅇ
아오

이 경우에 명령 오른쪽은 비어있으니 코드공간 바깥으로 따져야 할까요?
아니면 기능 없음(커서 방향을 바꾸지 않고 계속 진행)으로 처리해야 할까요?

@xbfld
Copy link

xbfld commented Apr 2, 2015

저는 빈 곳은 모두 ㅇ로 패딩이 되어있는 것 처럼 동작하는 것으로 이해했습니다. 이를테면

봥
ㅇ
븡
방방드디망희

와 같은 코드가 있다면

봥ㅇㅇㅇㅇㅇ
ㅇㅇㅇㅇㅇㅇ
븡ㅇㅇㅇㅇㅇ
방방드디망희

와 같이 생각하는 것이죠

@xbfld
Copy link

xbfld commented Apr 2, 2015

굳이 모든 홀소리가 쓰일 필요는 없다고 생각합니다. 닿소리의 기능은 하되 커서의 관성은 유지할 수 있는 홀소리를 남겨둬야 할 것 같습니다.

@youknowone
Copy link
Member Author

빈 곳을 패딩하는 방식은 구현에는 편의가 있지만 사용자를 배려하지 않는 방식이라고 생각됩니다.

가장 긴 열을 가진 줄에 영향을 받게 되는데 가장 긴줄이 몇글자인지 확인해야 다른 줄에서 의도한대로 동작하는지 확인할수 있습니다. 관련 없는 줄을 고쳤는데 동작이 바뀌는 경우가 생기겠죠. 아희 코드에서 코드 바깥에 주석을 다는 경우도 있는데 주석 길이에 따라 코드 동작이 달라지기도 할거구요.

줄 역시 마찬가지입니다. 프로그래밍에 널리 쓰이는 편집기 설정 중에는 마지막에 빈 줄 문자를 채워넣는 설정을 가진 경우가 있습니다. 편집기 설정에 따라 나도 모르게 마지막 줄이 빈 줄로 패딩되거나 할 수 있어요.

홀소리는 사용중인 홀소리가 결합된 꼴로 이루어진 4개만 추가됐습니다. ㅐ, ㅔ 계열과 그 계열이 포함된 홀소리는 계속 비어있습니다.

@disjukr
Copy link
Member

disjukr commented Apr 2, 2015

우
워어

이 코드에서 다음에는 무슨 명령이 오는 게 맞을까요?

@youknowone
Copy link
Member Author

현재 쓰여있는 룰에 따르면 다음과 같이 이동합니다.

좌로 1칸 이동 -> 코드 영역 밖이므로 코드 반대편인 '어'로 이동 -> 아래로 한칸 이동 -> 코드영역 밖이므로 코드 반대편(이자 제자리)인 '어'로 이동.

@disjukr
Copy link
Member

disjukr commented Apr 2, 2015

아, 그렇네요. 저 경우에는 직관에 의지하면 가 올 거라고 생각할 수 있지 않을까요?

@youknowone
Copy link
Member Author

ㅇㅇㅇㅇ
ㅇㅇㅇ
ㅇㅇ와ㅇㅇㅇㅇㅇ
ㅇㅇㅇㅇ
ㅇㅇㅇ
ㅇㅇ
ㅇ



이런 경우에 산으로 보내지 않고 적절하고 명확하면서도 직관적인 이동 기준이 있으면 좋겠다는 생각이 드는데 잘은 모르겠네요.

빈 칸을 모두 채우는 방식은 이동이 전혀 예측이 안되니 나쁜 방향이고, 그렇지 않은 방식 중에서 좋은 방식이 있으면 좋겠습니다.

@xbfld
Copy link

xbfld commented Apr 2, 2015

ㄱ기니드르
ㄴ와미와브
ㄷㄹㅁㅂㅅ

와 같은 코드에서 왼쪽과 오른쪽 와는 각각 어떻게 움직일지 궁금하네요

@youknowone
Copy link
Member Author

그 경우엔 명백하게 첫행의 니 르 로 가죠.

@xbfld
Copy link

xbfld commented Apr 2, 2015

제가 질문을 부정확하게 했네요. 홀소리 ㅘ에 의해 움직 인 다음 홀소리 ㅣ나 ㅡ를 만났을 때 이후에 대한 방향을 말하는 것이었습니다.

@youknowone
Copy link
Member Author

"커서 관성은 오른쪽과 위쪽 이동이 모두 보존됩니다."

두칸씩 이동하다 만나면 두칸이 뒤집히듯 ㅣ, ㅡ에서는 각각 한쪽만 뒤집어주면 되지 않을까 싶습니다. 불명확하게 보일수 있으니 명시하는쪽이 좋겠네요.

@youknowone
Copy link
Member Author

수정하면서 ㅟ, ㅚ도 함께 수정했습니다.

ㅘ로 우1상1로 이동하다 ㅟ를 만나면 좌1하1로 이동하게 될 것입니다.
ㅘ로 우1상1로 이동하다 ㅚ를 만나면 좌1상1로 이동하게 될 것입니다.

@puzzlet
Copy link
Member

puzzlet commented Apr 5, 2015

대각선 이동은 Funge-98처럼 '자기 자리로 되돌아오는 직선'의 끝으로 보내는 것도 괜찮다고 생각합니다. @lifthrasiir 님은 ㅑㅕㅛㅠ의 이동이 Funge-98과 다르다고 말씀하셨지만, 같은 직선을 타고 간다는 것만큼은 변하지 않으므로 일관성은 있어 보입니다.

수평/수직 이동을 따로따로 시키는 경우라면, 이동하는 도중에 명령을 실행시키지 않는다고 명시적으로 밝히는 편이 좋다고 생각합니다. 그리고 순서는 어떻게 하는 것이 좋을까요? 저는 ㅘ가 ㅗ+ㅏ니까 상1우1이라고 생각했는데, 우1상1으로 정하신 이유가 있나요?

@youknowone
Copy link
Member Author

제자리로 되돌아오는 건 좋은 것 같습니다.
이 경우 ㅛ, ㅠ의 경우에 코드가 가득차 있지 않은 경우 반대쪽 끝을 어떻게 정하냐의 문제만 정리를 하면 명확해지겠네요.
생각보다 이동 규칙기 복잡해져버려서 현재 상태보다는 이쪽이 더 마음에 듭니다.

좌우이동을 먼저 정한 이유는 좌우이동은 반드시 가운데에 빈 공간 없이 글자가 있다는 것이 보장되기 때문에 비어있을 가능성이 있는 상하보다 낫다고 생각했는데, ㅘ, ㅝ의 경우 어차피 빈 공간에 도달해서 좌우 이동을 다음차례에 또 해야하므로 큰 이득이 없어 보입니다.

@youknowone
Copy link
Member Author

홀소리 규칙을 수정했습니다. 한 가지 규칙으로 경계를 잘 설정할 수 있나 싶었는데 어려워서 사용자의 직관을 해치지 않는 최선의 방법이라 생각되는 방법으로 이동 방향별로 경계를 별도로 명시했습니다.

  • 좌우 이동은 이전과 비슷합니다.
  • 상하는 위쪽은 반드시 첫줄로 잡게 수정했습니다. 이는 ㅝ의 이동과 일관성을 유지하기 위함입니다.
  • ㅝ, ㅘ는 위에서 설명된 대로 자기자리로 되돌아오는 직선의 끝을 설정했습니다.

@Sait2000
Copy link

Sait2000 commented Oct 9, 2015

@youknowone

우ㅇㅇㅇ희
야ㅇ위ㅇㅇ
ㅇㅇㅇㅇㅇ

이 코드는 어떻게 동작하나요?

@youknowone
Copy link
Member Author

@Sait2000 쓰여 있는 규칙대로면 "위"에서 아래로 하나, 왼쪽으로 둘로 이동해야하는데 이 규칙대로면 코드가 점점 가속되는 문제가 발견되어... 좌우이동은 한칸만 하도록 고정시켰습니다. (어차피 항상 아래 이동 1이 있으므로)
최대 속도가 2인게 의도인데 이거도 명시하는게 좋겠어요.

@youknowone
Copy link
Member Author

모호한 표현 몇가지를 의미 변동 없이 손보고 다음 내용을 추가했습니다.

  • 명령의 실행순서 (같은 설명이지만 명확한 실행 순서를 추가)
    1. 닿소리를 먼저 실행합니다. 이때 진행방향 재정의가 있다면 재정의를 예약합니다.
    2. 홀소리에 따라 이동 방향을 결정합니다.
    3. 예약된 진행방향 재정의가 있다면 이동 방향을 변경합니다.
    4. 이동 방향에 따라 이동합니다.
  • utf-8이 아닌 문자가 ㅎ에 입력될 경우: ㅎ 받침이 왔지만 utf-8로 해석할 수 없는 문자가 입력될 경우 1바이트를 소비하고 진행방향을 뒤집습니다. (#제안-보완)
  • 숫자 입력 시 줄바꿈 문자 소비 처리: 단 0D('\r')와 0A('\n')가 연달아 나타나면 둘 모두 소비시킵니다.

10주년 기념 새 판을 만들려면 관심을 갖고 쳐다봤어야 했는데 해를 넘겨서 2016년이 되어버렸네요.
기능 추가 때문에 이야기가 쉽지 않은데 이전 스펙에서 빠진 동작을 추가하거나 권고하는 내용은 스펙 문서 개정으로 따로 PR 만들겠습니다

@youknowone
Copy link
Member Author

보충해도 좋고 안해도 좋다고 생각되는 내용이 하나 떠올랐습니다. 아희의 코드가 완전한 UTF-8 텍스트가 아닐 때는 어떻게 해야할까요? 실행을 거부할 수도 있고 적당히 실행할수도 있을텐데, 아희 특성상 "오류가 있는 지점까지만 해석한다" 또는 "오류 이후에는 복구를 시도한다" 같은 동작은 코드가 보이는 것과 완전히 다르게 실행될 여지가 있을것 같네요.

@Sait2000
Copy link

Sait2000 commented Feb 3, 2016

진행방향이 (위|아래)일 때 진행방향의 (끝|반대쪽 끝)이 그 열에서 가장 처음에 나타나는 줄이 되는 게 일관성 있지 않나요?

또 아래 코드에서처럼 진행방향이 왼쪽 위일 때와 오른쪽 아래일 때의 끝과 반대쪽 끝을 정의해야 합니다.

유
희
우치
와

@youknowone
Copy link
Member Author

중간에 본문 수정을 하면서 에 대한 설명과 이동 경로에 대한 설명이 안 맞게 된 부분이 있네요. 의도한 부분은 진행 방향이 오른쪽 위인 경우 진행 방향의 끝은 첫 줄이고 반대편 끝은 출발점에서 진행 방향의 끝까지 그은 연장선 중 첫 열을 지나는 점입니다. 입니다.

@youknowone
Copy link
Member Author

위|아래 일때는 처음에는 그렇게 잡았었는데, 대각선 이동시 항상 첫행과 첫열을 기준으로 잡으면서 일관성 있게 잡느라 조정했던 기억이 납니다. 어떻게 잡는게 더 일관성 있게 보이는 동작이 될까요?

@Sait2000
Copy link

Sait2000 commented Feb 3, 2016

모든 경우에 끝은 진행 방향 쪽 마지막 문자, 반대쪽 끝은 진행 방향 반대쪽 마지막 문자로 하면 진행 방향이 왼쪽, 오른쪽일 때는 지금과 같은 결과가 나오고 대각선 이동의 경우에는 실행결과가 같으니 괜찮지 않을까요?

그리고 첫 줄에 한글 낱자가 없을 때는 첫 줄을 무시하게 하는 건 어떨까요? 그렇게 하면 shebang 라인 등으로 인해 진행 방향이 위|아래일 때 끝이 바뀌는 경우를 피할 수 있으니까요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants