존재하지 않는 언어에 대한 통역사 제작


18

입력을 받고 해석하여 결과를 숫자 배열로 출력하는 가짜 스택 기반 언어에 대한 인터프리터를 작성하십시오. 각 바이트를 반복하고이 테이블에 따라 다른 기능을 수행해야합니다.

0000 (0) : 연결 (문자열 인 것처럼 스택에서 맨 위 두 숫자를 결합합니다. 예 : 12,5-> 125)
0001 (1) : 증분 (스택 상단의 숫자에 1을
더함 ) 0010 (2) : 감소 (스택 상단의 숫자에서 1 빼기)
0011 (3) : 곱하기 (스택의 상단 두 숫자 곱하기)
0100 (4) : 나누기 (두 번째에서 두 번째 숫자로 나누기) 스택 상단 참조)
0101 (5) 추가 (두 숫자 스택의 최상위를 추가)
0110 (6) 빼기 (아래 하나)에서 스택의 최상위 수를 뺀다
0111 (7) : 지수 ( 2 차에서 1까지의 수를 최고 수의 거듭 제곱으로 계산하십시오.
1000 (8) : 계수 : (두 번째에서 최고 수의 모듈로를 계산하십시오)
1001 (9) : 오른쪽으로 회전 (스택 하나를 아래로 이동하십시오. 맨 아래의 숫자는 이제 맨 위에 있습니다.)
1010 (A) : 왼쪽으로 회전 (스택을 하나 위로 이동하십시오.
1011 (B) : 복제 (상위 숫자가 두 번 나타나도록 복사합니다. 예 : 4,1은 4,1,1이됩니다)
1100 (C) : 이중 복제 (스택에서 상위 두 숫자를 복사합니다. 예 : 4, 1,2는 4,1,2,1,2가 됨)
1101 (D) : 스왑 (스택에서 상위 2 개의 숫자를 바꿉니다. 예 : 4,1,2는 4,2,1이됩니다)
1110 (E) : 이중 스왑 (상위 두 숫자를 그 아래에 두 숫자로 바꿉니다. 예 : 1,2,3,4,5는 1,4,5,2,3이됩니다)
1111 (F) : 삭제 / 팝 (위의 숫자 제거) 스택)

예를 들어,

1 1 BC 5 C 5 B 9 5-입력 (16 진)
| | | | | | | | | |
1212 6 6 2 8-스택
    2 2 2 4 6 6 6
      2 4 2 4 6 4
      2 2 2 4 2
          2 2 2

출력 [8,6,4,2]

규칙 :

  • 유니 코드 / 기호는 괜찮지 만 ASCII가 가장 좋습니다.
  • 창의력을 발휘하십시오! 부족은 중요하지만 창의력은 훌륭합니다!
  • 바이트가 너무 어려운 경우, 사용 "$iv*/+-^%><dtsz."또는 "0123456789ABCDEF"대신 실제 바이트.
  • 속도! 빠를수록 좋습니다.
  • 점수는 평판을 기반으로하지만 크기는 큰 요소입니다.

보너스:

완료하려고 가능한 한 문자열의 짧은으로 새로 만든 인터프리터를 사용하여 도전을.

노트 :

다른 코드 골프 문제와 달리이 문제를 해결하는 것은 이것으로 처리 할 코드가 없다는 것입니다. 만약 당신이 brainf * ck 인터프리터를 작성해야한다면, 다른 사람들의 구현을 볼 수 있습니다. 이것으로, 당신은 그렇게 할 수 없습니다.


나는 이것에 날짜를 넣고 잊는 것을 잊었다. 나는 이것을 만들 때부터 한 달 안에 만들 것이라고 생각합니다. 2 월 22 일에 가장 많은 표를 얻은 사람이 승리합니다!


1
우승자가 투표에 의해 결정된다고 말하면 code-golf가 아니라 인기 경연 대회 입니다.
Ry-

8
더 이상 존재하지 않습니까? :)
Kendall Frey

1
기술적 으로 언어는 언어가되기 위해 통역사 나 컴파일러가 필요하지 않습니다. : P
Kendall Frey

2
IIUC, 빈 스택으로 시작하여 언더 플로를 0으로 처리해야합니까?
John Dvorak

2
스택에서 단일 0으로 시작해야합니다 (시작할 숫자가 없으면 아무것도 할 방법이 없으므로). 나는 당신에게 언더 플로우를 남겨 둘 것입니다. 더 쉬운 것.
Taconut

답변:


14

루비, 67 줄의 정규식 대체

효율적인 알고리즘을 고수하면서 정규식으로 인터프리터를 작성하기로 결정했습니다.

평범한 바이트로 갈 수 있었지만 기호를 사용하면 코드를 더 읽기 쉽게 만듭니다. 물론 하나의 바이트에 두 개의 명령어를 넣을 수 있다면 ...

음수 값을 연결하면 내부 표현을 반영하여 10의 보수 동작이 발생합니다.

나눗셈은 정수 나누기이며 나머지는 절대 음수가 아닙니다.

subs = [
  # stack expansion
  [/^ ?([$iv*\/+\-^%dtsz.])/,  ' 0 \1'  ],
  [/^ (\d+ [$*\/+\-^%tsz])/,   ' 0 \1'  ],
  [/^ ((\d+ ){2,3}z)/,         ' 0 \1'  ],
  [/ (0|9)\1+/,                ' \1'    ],
  # concatenation
  [/ (\d+) (?:0+|9+)(\d+) \$/, ' \1\2 ' ], 
  [/ (\d+) (0|9) \$/,          ' \1\2 ' ],
  # swaps
  [/ ((?:\d+ )*)(\d+) </,      ' \2 \1' ],
  [/ (\d+)((?: \d+)*) >/,      '\2 \1 ' ],
  [/ (\d+) (\d+) s/,           ' \2 \1 '],
  [/ (\d+ \d+) (\d+ \d+) z/,   ' \2 \1 '],
  # dups
  [/ (\d+) d/,                 ' \1 \1 '],
  [/ (\d+ \d+) t/,             ' \1 \1 '],
  # pop
  [/ (\d+) \./,                ' '      ],

  # increment / decrement
  [/ (\d+) i/, ' \1I '], [/ (\d+) v/, ' \1V '],
  *(%w[0I 1I 2I 3I 4I 5I 6I 7I 8I 9I].zip [*?1..?9, 'I0']),
  *(%w[0V 1V 2V 3V 4V 5V 6V 7V 8V 9V].zip ['V9', *?0..?8]), 
  [' 1', ' 01'], [' 8', ' 98'], [' I', ' '], [' V', ' '],
  # addition, subtraction
  [/ (\d+) (\d+) \+/,                ' \1P \2P '       ], #init addition
  [/ (\d+) (\d+) \-/,                ' \1S \2S '       ], #init subtraction
  [/ ([PS](\d)\w*) (\d+[PS]\w*) /,   ' \2\1 \3 '       ], #sign extend left
  [/ (\d+[PS]\w*) ([PS](\d)\w*) /,   ' \1 \3\2 '       ], #sign extend right
  [/ (\d*)(\d)P(\S*) (\d*)0P(0*) /,  ' \1P\2\3 \4P0\5 '], #advance addition
  [/ (\d*)(\d)S(\S*) (\d*)0S(0*) /,  ' \1S\2\3 \4S0\5 '], #advance subtraction
  [/ (\d+)P(\S*) (\d*[1-5])P(0*) /,  ' \1IP\2 \3VP\4 ' ], #transfer left
  [/ (\d+)P(\S*) (\d*[6-9])P(0*) /,  ' \1VP\2 \3IP\4 ' ], #transfer right
  [/ (\d+)S(\S*) (\d*[1-5])S(0*) /,  ' \1VS\2 \3VS\4 ' ], #decrement both
  [/ (\d+)S(\S*) (\d*[6-9])S(0*) /,  ' \1IS\2 \3IS\4 ' ], #increment both
  [/ [PS](\S+) [PS]0+ /,             ' \1 '            ], #finish 

  # digitwise negation
  *(%w[9N 8N 7N 6N 5N 4N 3N 2N 1N 0N].zip [*'N0'..'N9']),
  #multiplication and division by 2
  *([*'H0'..'H9'].zip %w[0H 0F 1H 1F 2H 2F 3H 3F 4H 4F]),
  *([*'F0'..'F9'].zip %w[5H 5F 6H 6F 7H 7F 8H 8F 9H 9F]),  
  *(%w[0T 1T 2T 3T 4T 5T 6T 7T 8T 9T].zip %w[T0 T2 T4 T6 T8 TI0 TI2 TI4 TI6 TI8]), 
  ['H ', ' '], [' T', ' '],

  # sign correction for */%
  [/ (\d+) (9\d*) ([*\/%])/, ' \1NI \2NI \3'], [' N', ' '],
  # multiplication
  [/ (0+ \d+|\d+ 0+) \*/,     ' 0 '          ], #multiplication by zero
  [/ (\d+) (0\d*[02468]) \*/, ' \1T H\2 *'   ], #multiplication by an even number
  [/ (\d+) (0\d*[13579]) \*/, ' \1 \1 \2V *+'], #multiplication by an odd number
  # division / modulo
  [?/, 'r.'], [?%, 'rs.'],
  [/ (0|9)(\d*) (0\d+) r/,           ' \3 0 \1D\2 '          ], #init division
  [/ (\d+) (\d+) (0\d*)D(\d*) /,     ' \1 \2I \3SD\4 \1S '   ], #subtract divisor
  [/ (\d+) (\d+) (9\d*)D(\d)(\d*) /, ' \1 \2V0 \3P\4D\5 \1P '], #add divisor and advance
  [/ (\d+) (\d+) (9\d*)D /,          ' \2V \3P \1P '         ], #add divisor and finish  

  #exponentiation
  [/ \d+ 0+ \^/,             ' 01 '          ], # case: zeroth power
  [/ 9\d+ 9+ \^/,            ' 9 '           ], # case: reciprocal of negative
  [/ \d+ 9\d+ \^/,           ' 0 '           ], # case: high negative power
  [/ 0\d+ 9\d+ \^/,          ' 0 '           ], # case: reciprocal of positive
  [/ (\d+) 0+1 \^/,          ' \1 '          ], # case: power of one
  [/ (\d+) (\d*[02468]) \^/, ' \1 \1 *H\2 ^' ], # case: even exponent
  [/ (\d+) (\d*[13579]) \^/, ' \1 \2V ^\1 *' ], # case: odd exponent
]                                   

x = gets.tr '^$iv*/+\-^%><dtsz.', ''
until x =~ /^ (\d+ )*$/
  subs.each do |sub|
    x.sub!(*sub) # && (puts x; sleep 0.1)
  end
end

보너스 라운드와 관련하여 내가 찾은 가장 짧은 솔루션 ( 13 자 )은 깨끗한 솔루션입니다.

iistisii$<$<$

당신의 보너스 솔루션은 초기없는 날 것으로 보인다 d(이후 ii, 스택이 포함되어 있지 않습니다 2 , 두 번째는 변장 단지 스왑입니다 (물론, 적어도 첫 번째,와 스왑에 아무것도), 마지막 회전을 ... )는 오른쪽이 아니라 왼쪽에 있어야합니다.
Mormegil

@ Mormegil 나는 스택이 필요에 따라 0으로 자동 확장된다는 해석을 사용하고 있습니다. 따라서 선행 0을 두배로 할 필요가 없습니다. 회전 방향에 관해서는, 나는 다시 점검 할 것이다 ...
John Dvorak

@Mormegil 회전 방향은 고정되어 있습니다.
John Dvorak

오, 예, 언더 플로 해석에 대한 의견을 놓쳤으며 불행히도 내 솔루션은 그렇게 할 수 없습니다.
Mormegil

11

x86 어셈블리 (Win32)

“SPEED!”는 여기서 매우 중요해 보이며, 우리는 모두 어셈블리 언어를 능가하는 것을 알고 있습니다. 자, 그것을 조립하자!

이것은 x86 어셈블리 언어 (NASM 구문)로 언어를 구현 한 것으로, 숫자는 네이티브 x86 스택을 직접 사용하여 부호없는 32 비트 정수로 저장되고 해석됩니다. 산술 연산 (또는 0으로 나누기) 중 스택 언더 플로 및 오버플로는 런타임 오류이며 오류 메시지로 프로그램을 종료합니다.

        global _start

        extern _GetCommandLineA@0
        extern _GetStdHandle@4
        extern _CreateFileA@28
        extern _GetFileSize@8
        extern _LocalAlloc@8
        extern _ReadFile@20
        extern _CloseHandle@4
        extern _WriteFile@20

section .text

; ---------------------------------------------------------------------------------------
; Initialization
; ---------------------------------------------------------------------------------------

_start:
        ; Retrieve command line
        CALL _GetCommandLineA@0

        ; Skip argv[0]
        MOV ESI, EAX
        XOR EAX, EAX
skipuntilspace:
        MOV AL, [ESI]
        INC ESI
        TEST EAX, EAX
        JE missingparam
        CMP EAX, ' '
        JNE skipuntilspace
        INC ESI

        ; Open the file
        PUSH 0
        PUSH 80h
        PUSH 3
        PUSH 0
        PUSH 1
        PUSH 80000000h
        PUSH ESI
        CALL _CreateFileA@28
        CMP EAX, -1
        JE  cannotopenfile

        ; Get its size
        PUSH EAX
        PUSH 0
        PUSH EAX
        CALL _GetFileSize@8

        PUSH EAX

        ; Allocate memory buffer
        PUSH EAX
        PUSH 0
        CALL _LocalAlloc@8
        TEST EAX, EAX
        MOV ESI, EAX
        JZ outofmemory

        POP ECX
        POP EAX
        PUSH EAX

        ; Store end-of-program pointer
        MOV [programend], ESI
        ADD [programend], ECX

        ; Read the file contents
        PUSH 0
        PUSH buff
        PUSH ECX
        PUSH ESI
        PUSH EAX
        CALL _ReadFile@20
        TEST EAX, EAX
        JZ cannotopenfile

        ; Close the file
        CALL _CloseHandle@4

; ---------------------------------------------------------------------------------------
; Main loop of the interpreter
; ---------------------------------------------------------------------------------------

        ; Store the end of stack into EBP
        MOV EBP, ESP

        ; Push an initial 0 onto the stack
        XOR EAX, EAX
        PUSH EAX

mainloop:
        ; Load the next opcode, if not end of program
        XOR EAX, EAX
        CMP ESI, [programend]
        MOV AL, [ESI]
        JAE endloop
        LEA ESI, [ESI+1]

        ; Check if the opcode is valid
        CMP EAX, (maxop - opcodetable) / 8
        JA  fault_invalidopcode

        ; Check for required stack space
        MOV ECX, [opcodetable + 8 * EAX + 4]
        LEA EDI, [ESP + ECX]
        CMP EDI, EBP
        JA  fault_stackunderflow

        ; Jump to the respective opcode handler
        MOV EAX, [opcodetable + 8 * EAX]
        JMP EAX

; ---------------------------------------------------------------------------------------
; Implementation of the specific operations
; ---------------------------------------------------------------------------------------

        ; ************** CAT 0000 (0): Concatenate (Combine top two numbers in a stack as if they were a string. ex: 12,5 -> 125)
op_concatenate:
        POP EBX
        POP EAX
        MOV ECX, EAX
        MOV EDI, 10
concat_loop:
        XOR EDX, EDX
        SHL EBX, 1
        DIV EDI
        LEA EBX, [4 * EBX + EBX]
        TEST EAX, EAX
        JNZ concat_loop

        ADD EBX, ECX
        PUSH EBX
        JMP mainloop

        ; ************** INC 0001 (1): Increment (Add 1 to the number on the top of the stack)
op_increment:
        POP EAX
        ADD EAX, 1
        PUSH EAX
        JNC mainloop
        JMP fault_intoverflow

        ; ************** DEC 0010 (2): Decrement (Subtract one from the number at the top of the stack)
op_decrement:
        POP EAX
        SUB EAX, 1
        PUSH EAX
        JNC mainloop
        JMP fault_intoverflow

        ; ************** MUL 0011 (3): Multiply (Multiply the top two numbers in the stack)
op_multiply:
        POP EAX
        POP EDX
        MUL EDX
        TEST EDX, EDX
        PUSH EAX
        JZ mainloop
        JMP fault_intoverflow

        ; ************** DIV 0100 (4): Divide (Divide the 2nd-to-top number by the top number on the stack)
op_divide:
        POP ECX
        TEST ECX, ECX
        POP EAX
        JZ fault_dividebyzero
        XOR EDX, EDX
        DIV ECX
        PUSH EAX
        JMP mainloop

        ; ************** MOD 0101 (5): Add (Add the top two numbers on the stack)
op_add:
        POP EAX
        ADD [ESP], EAX
        JNC mainloop
        JMP fault_intoverflow

        ; ************** SUB 0110 (6): Subtract (Subtract the top number on the stack from the one below it)
op_subtract:
        POP EAX
        SUB [ESP], EAX
        JNC mainloop
        JMP fault_intoverflow

        ; ************** EXP 0111 (7): Exponent (Calculate the second-to-top number to the power of the top number)
op_exponent:
        POP ECX
        POP EBX
        MOV EAX, 1
exploop:
        TEST ECX, 1
        JZ expnomult
        MUL EBX
        TEST EDX, EDX
        JNZ fault_intoverflow
expnomult:
        SHR ECX, 1
        JZ expdone
        XCHG EAX, EBX
        MUL EAX
        TEST EDX, EDX
        XCHG EAX, EBX
        JZ exploop
        JMP fault_intoverflow
expdone:
        PUSH EAX
        JMP mainloop

        ; ************** MOD 1000 (8): Modulus: (Find the second-to-top number modulo the top one)
op_modulus:
        POP ECX
        TEST ECX, ECX
        POP EAX
        JZ fault_dividebyzero
        XOR EDX, EDX
        IDIV ECX
        PUSH EDX
        JMP mainloop

        ; ************** ROR 1001 (9): Rotate Right (Shift the stack down one. The number on the bottom is now on the top)
op_rotright:
        MOV EAX, [EBP - 4]
        LEA ECX, [EBP - 4]
        SUB ECX, ESP
        MOV EDX, ESI
        SHR ECX, 2
        LEA EDI, [EBP - 4]
        LEA ESI, [EBP - 8]
        STD
        REP MOVSD
        MOV [ESP], EAX
        CLD
        MOV ESI, EDX
        JMP mainloop

        ; ************** ROL 1010 (A): Rotate Left (Shift the stack up one. The number on the top is now on the bottom)
op_rotleft:
        MOV EAX, [ESP]
        LEA ECX, [EBP - 4]
        SUB ECX, ESP
        MOV EDX, ESI
        SHR ECX, 2
        LEA ESI, [ESP + 4]
        MOV EDI, ESP
        REP MOVSD
        MOV [EBP - 4], EAX
        MOV ESI, EDX
        JMP mainloop

        ; ************** DUP 1011 (B): Duplicate (Copy the top number so that it appears twice. ex: 4,1 becomes 4,1,1)
op_duplicate:
        PUSH DWORD [ESP]
        JMP mainloop

        ; ************** DU2 1100 (C): Double Duplicate (Copy the top two numbers on the stack. ex: 4,1,2 becomes 4,1,2,1,2)
op_dblduplicate:
        PUSH DWORD [ESP+4]
        PUSH DWORD [ESP+4]
        JMP mainloop

        ; ************** SWP 1101 (D): Swap (Swap the top two numbers on the stack. ex: 4,1,2 becomes 4,2,1)
op_swap:
        POP EAX
        POP EDX
        PUSH EAX
        PUSH EDX
        JMP mainloop

        ; ************** SW2 1110 (E): Double Swap (Swap the top two numbers with two below them.ex: 1,2,3,4,5 becomes 1,4,5,2,3)
op_dblswap:
        POP EAX
        POP EBX
        POP ECX
        POP EDX
        PUSH EBX
        PUSH EAX
        PUSH EDX
        PUSH ECX
        JMP mainloop

        ; ************** POP 1111 (F): Delete/Pop (Remove the number at the top of the stack)
op_pop:
        POP EAX
        JMP mainloop


; ---------------------------------------------------------------------------------------
; End of the program: print out the resulting stack and exit
; ---------------------------------------------------------------------------------------

endloop:
        MOV ESI, ESP

printloop:
        CMP ESI, EBP
        JNB exit
        MOV EAX, [ESI]
        MOV EBX, ESI
        PUSH EBX
        CALL printnum
        POP EBX
        LEA ESI, [EBX + 4]
        JMP printloop

exit:
        MOV ESP, EBP
        ;POP EAX
        XOR EAX, EAX
        RET


; ---------------------------------------------------------------------------------------
; Faults
; ---------------------------------------------------------------------------------------

fault_invalidopcode:
        MOV EAX, err_invalidopcode
        JMP fault

fault_stackunderflow:
        MOV EAX, err_stackunderflow
        JMP fault

fault_dividebyzero:
        MOV EAX, err_dividebyzero
        JMP fault

fault_intoverflow:
        MOV EAX, err_intoverflow
        JMP fault

fault:
        CALL print
        MOV EAX, crlf
        CALL print

        MOV ESP, EBP
        MOV EAX, 1
        RET


missingparam:
        MOV EAX, err_missingparameter
        JMP fault

cannotopenfile:
        MOV EAX, err_cannotopenfile
        JMP fault

outofmemory:
        MOV EAX, err_outofmemory
        JMP fault

; ---------------------------------------------------------------------------------------
; Helper functions
; ---------------------------------------------------------------------------------------

printnum:
        MOV EBX, 10
        CALL printnumrec
        MOV EAX, crlf
        JMP print

printnumrec:
        PUSH EAX
        PUSH EDX
        XOR EDX, EDX
        DIV EBX
        TEST EAX, EAX
        JZ printnumend
        CALL printnumrec
printnumend:
        MOV EAX, EDX
        CALL printdigit
        POP EDX
        POP EAX
        RET


printdigit:
        ADD EAX, '0'
        MOV [printbuff], EAX
        MOV EAX, printbuff
        JMP print


print:
        MOV  ESI, EAX
        PUSH 0
        PUSH buff
        CALL strlen
        PUSH EAX
        PUSH ESI
        PUSH -11
        CALL _GetStdHandle@4
        PUSH EAX
        CALL _WriteFile@20
        RET

strlen:
        XOR ECX, ECX
strlen_loop:
        CMP BYTE [ESI+ECX], 0
        JE strlen_end
        LEA ECX, [ECX+1]
        JMP strlen_loop
strlen_end:
        MOV EAX, ECX
        RET


; ---------------------------------------------------------------------------------------
; Data
; ---------------------------------------------------------------------------------------

section .data

; Table of opcode handlers and required stack space (in bytes, i.e. 4*operands)
opcodetable:
        DD op_concatenate, 8
        DD op_increment, 4
        DD op_decrement, 4
        DD op_multiply, 8
        DD op_divide, 8
        DD op_add, 8
        DD op_subtract, 8
        DD op_exponent, 8
        DD op_modulus, 8
        DD op_rotright, 0
        DD op_rotleft, 0
        DD op_duplicate, 4
        DD op_dblduplicate, 8
        DD op_swap, 8
        DD op_dblswap, 16
        DD op_pop, 4
maxop:

crlf                    DB 13, 10, 0
err_invalidopcode       DB "Invalid opcode", 0
err_stackunderflow      DB "Stack underflow", 0
err_dividebyzero        DB "Division by zero", 0
err_intoverflow         DB "Integer overflow", 0

err_missingparameter:   DB "Missing parameter: Use nexlang file.bin", 0
err_cannotopenfile:     DB "Unable to open input file", 0
err_outofmemory:        DB "Not enough memory", 0

section .bss

programend      RESD 1
printbuff       RESD 1
buff            RESD 1

이것을 컴파일하려면 다음과 같은 것을 사용하십시오

nasm.exe -fwin32 nexlang.asm
ld -o nexlang.exe -e _start nexlang.obj -s -lkernel32

프로그램은 명령 행에서 프로그램을 포함하는 이진 파일의 이름을받습니다 (예 :) nexlang.exe testprg.bin. 완료되면 스택의 최종 내용을 사람이 읽을 수있는 형식으로 표준 출력에 인쇄합니다.

테스트를 돕기 위해 다음을 저장하십시오 nex.def.

%define CAT DB 00h
%define INC DB 01h
%define DEC DB 02h
%define MUL DB 03h
%define DIV DB 04h
%define ADD DB 05h
%define SUB DB 06h
%define EXP DB 07h
%define MOD DB 08h
%define ROR DB 09h
%define ROL DB 0Ah
%define DUP DB 0Bh
%define DU2 DB 0Ch
%define SWP DB 0Dh
%define SW2 DB 0Eh
%define POP DB 0Fh

그런 다음 위에서 정의한 니모닉을 사용하여 NEX (질문 제목에 명시된 "존재하지 않는") 프로그램을 작성하고 다음과 같이 컴파일하십시오.

nasm.exe -p nex.def -o prg.bin prg.nex

예를 들어 원래 테스트 케이스의 경우 다음을 사용하십시오 prg.nex.

INC     ; 1
INC     ; 2
INC     ; 3
INC     ; 4
DUP     ; 4 4
DU2     ; 4 4 4 4
ADD     ; 8 4 4
DU2     ; 8 4 8 4 4
ADD     ; 12 8 4 4
DUP     ; 12 12 8 4 4
ROR     ; 4 12 12 8 4
ADD     ; 16 12 8 4

마지막으로, "2014"챌린지에는 다음 14 바이트 NEX 프로그램을 사용하십시오.

DUP     ; 0 0
DUP     ; 0 0 0
INC     ; 1 0 0
INC     ; 2 0 0
SWP     ; 0 2 0
CAT     ; 20 0
SWP     ; 0 20
INC     ; 1 20
DUP     ; 1 1 20
INC     ; 2 1 20
INC     ; 3 1 20
INC     ; 4 1 20
CAT     ; 14 20
CAT     ; 2014

LEA ESI, [ESI+1]아니라 INC ESI?
Score_Under

실제로, 최종 결과에서 실제 이유는 없습니다. 일반적으로 속도 / 크기 / 영향을받는 플래그가 중요 할 수 있습니다. 그러나 결과를 실제로 최적화하지는 않았지만 기본적으로 첫 번째 시도입니다.
Mormegil

1
이것은 확실히 가장 시원합니다. 나는 그것으로 놀면서 많은 즐거움을 얻었습니다. :).
Taconut

9

GolfScript, 64 자

OK, 그래서 나는 이것을 시도하고 골프하기로 결정했습니다. 그리고 GolfScript보다 골프에 더 좋은 언어는 무엇입니까?

편리하게도 GolfScript 자체는 이미 단일 바이트 명령이 포함 된 스택 기반 언어이며 16 개의 명령 중 11 개가 내장 GolfScript 명령에 직접 매핑됩니다. 따라서 귀하의 언어를 해석하기 위해 실제로해야 할 일은 GolfScript에서 나머지 5 개의 명령을 구현하고 번역 테이블을 작성하는 것입니다.

0\{'`+~
)
(
*
/
+
-
?
%
](+~
])\~
.
1$1$
\
[@]\+~\
;'n%=~}/]-1%`

번역 테이블의 구분 기호로 줄 바꿈을 사용하기 때문에 코드가 널리 퍼져 있습니다. 초기 0\값은 스택에 0을 넣고 입력 프로그램 아래로 이동합니다. { }/코드의 대부분을 포함하는 루프는 스택에서 입력 된 프로그램을 얻어 그 문자의 각각을 통해 루프 본문을 반복하여 최종 ]-1%`수집하여 배열로 스택의 상단으로부터 샘플 출력 시작하기 때문에 (이것은 반전 스택)하고 문자열 화합니다.

루프 본문은 16 줄 작은 따옴표 문자열로 시작합니다. n%이 문자열을 줄 바꿈으로 나누고 =입력 문자에 해당 ~하는 하위 문자열을 찾은 다음 하위 문자열을 GolfScript 코드로 평가합니다.

마지막으로 16 가지 명령의 GolfScript 구현은 다음과 같습니다.

  • 0 = `+~: 두 숫자를 문자열로 연결
  • 1 = ): 증분
  • 2 = (: 감소
  • 3 = *: 곱하기
  • 4 = /: 나누기
  • 5 = +: 추가
  • 6 = -: 빼기
  • 7 = ?: 힘을 올리다
  • 8 = %: 계수
  • 9 = ](+~: 스택을 오른쪽으로 회전
  • A = ])\~: 스택을 왼쪽으로 회전
  • B = .: 복제
  • C = 1$1$: 이중 복제
  • D = \: 스왑
  • E = [@]\+~\: 이중 스왑
  • F = ;: 팝

이중 스왑에 만족하지 못합니다. 다른 명령보다 못 생기고 훨씬 길었습니다. 더 좋은 방법이 있어야한다고 생각하지만, 그렇다면 아직 찾지 못했습니다. 그래도 적어도 작동합니다.

예를 들어 위의 프로그램을 입력에서 실행하십시오 (GolfScript / Ruby / Perl / Python 등으로 큰 따옴표로 묶인 문자열로 제공).

"\x01\x01\x0B\x0C\x05\x0C\x05\x0B\x09\x05"

출력을 산출합니다 :

[8 6 4 2]

편집 : 나는 번역 테이블의보다 컴팩트 한 인코딩을 사용하여 총 62 자에 대해 두 개의 문자를 더 저장할 수있었습니다 . 그러나 가독성을 희생합니다.

0\{(')(*/+-?%'1/'](+~
])\~
.
1$1$
\
[@]\+~\
;
`+~'n/+=~}/]-1%`

이 버전의 주목할만한 기능은 (루프 시작 부분에를 포함하여 명령 색인을 0..15에서 -1..14로 이동하여 한 문자 명령의 긴 시퀀스를 1에서 8로 시작할 수 있습니다. 테이블의. 이를 통해 별도의 문자열로 저장할 수 있고 구분하는 8 개의 줄 바꿈을 제거 할 수 있습니다. 아아, 여분의 복잡성은 다른 곳에서 6 자의 비용이 든다.


당신은 떨어질 수 +])\+~
존 드보락

@ JanDvorak : 아, 맞습니다. 감사!
Ilmari Karonen

8

하스켈

재미를 위해 변수 를 사용 하지 않고 함수를 결합 하는 솔루션을 만들었 습니다.

import Control.Applicative
import Control.Monad
import Control.Monad.State
import Data.Function

type SM = State [Int]

pop :: SM Int
pop = state ((,) <$> head <*> tail)

push :: Int -> SM ()
push = modify . (:)

popN :: Int -> SM [Int]
popN = sequence . flip replicate pop

pushN :: [Int] -> SM ()
pushN = mapM_ push

rotL, rotR :: Int -> [a] -> [a]
rotL = (uncurry (flip (++)) .) . splitAt
rotR = (reverse .) . flip (flip rotL . reverse)

step :: Int -> SM ()
step 0x00 = push =<< ((read .) . on (++) show) <$> pop <*> pop
step 0x01 = push . (+ 1) =<< pop
step 0x02 = push . subtract 1 =<< pop
step 0x03 = push =<< (*) <$> pop <*> pop
step 0x04 = push =<< flip div <$> pop <*> pop
step 0x05 = push =<< (+) <$> pop <*> pop
step 0x06 = push =<< flip (-) <$> pop <*> pop
step 0x07 = push =<< flip (^) <$> pop <*> pop
step 0x08 = push =<< flip mod <$> pop <*> pop
step 0x09 = modify $ (:) <$> last <*> init
step 0x0A = modify $ rotL 1
step 0x0B = pop >>= pushN . replicate 2
step 0x0C = popN 2 >>= pushN . concat . replicate 2
step 0x0D = popN 2 >>= pushN . rotL 1
step 0x0E = popN 4 >>= pushN . rotL 2
step 0x0F = void pop

run :: [Int] -> [Int]
run = flip execState [0] . mapM_ step

6

루비, (330) 316 자

나는 골프를하기로 결정했다. (항상 재미 있기 때문입니다.)

s=[0]
o=->c{t=s.pop;s.push s.pop.send(c,t)}
gets.chop.each_char{|c|eval %w[t=s.pop;s.push"#{s.pop}#{t}".to_i s[-1]+=1 s[-1]-=1 o[:*] o[:/] o[:+] o[:-] o[:**] o[:%] s.rotate! s.rotate!(-1) s.push(s[-1]) s.concat(s[-2..-1]) s[-1],s[-2]=s[-2],s[-1] s[-1],s[-2],s[-3],s[-4]=s[-4],s[-3],s[-1],s[-2] s.pop][c.to_i 16]}
p s

주요 부분은 다음과 같습니다.

gets.chop.each_char{|c|eval [(huge array of strings)][c.to_i 16]}

각 16 진수를 10 진수로 변환 한 다음를 사용하여 [(huge array of strings)]해당 명령을 나타내는 올바른 문자열을 찾습니다. 그런 다음 eval해당 문자열입니다.

이 ( %w[x y z]는)와 동일합니다 ['x','y','z'].

나는 또한 당신이 그 라인에서 웃는 얼굴을 찾는 방법을 좋아합니다! 그들 중 일부는

  • :*
  • :/
  • :-]
  • :%

샘플 실행 :

c:\a\ruby>random_cg_lang
11BC5C5B95
[2, 4, 6, 8]

4

C - 642 634 자

의 경우 $iv*/+-^%><dtsz.에만 방언 (추가 q와 함께, 종료 문자로 0) :

#define P s=*t;a=realloc(a,--w<<2);t=a+w-1;
#define H(n)a=realloc(a,(w+=n)<<2);
#define B(n)break;case n:
*a,*t,s,w=1,i;main(){t=a=calloc(4,1);while((i=getchar())&&i^'q')switch(i){B(36)P*t*=pow(10,((
int)log10(s))+1);*t+=s;B(105)++*t;B(118)--*t;B(42)P*t*=s;B(47)P*t/=s;B(43)P*t+=s;B(45)P*t-=s;
B(94)P*t=pow(*t,s);B(37)P*t%=s;B(62)s=*a;memcpy(a,a+1,(w-1)<<2);*t=s;B(60)s=*t;memcpy(a+1,a,(
w-1)<<2);*a=s;B(100)H(1)t=a+w-2;s=*t;t++;*t=s;B(116)H(2)t=a+w-1;t[-1]=t[-3];*t=t[-2];B(115)s=
*t;*t=t[-1];t[-1]=s;B(122)s=*t;*t=t[-2];t[-2]=s;s=t[-1];t[-1]=t[-3];t[-3]=s;B(46)P}putchar('[
');putchar(32);while(w)printf("%i ",a[--w]);putchar(']');}

2014 년 과제 해결 방법 : dididiizs>.


당신이 잃을 수 있다고 생각합니다 free(a);. 그리고, 그것은 안 <<2realloc전화?
luser droog

@luserdroog 사실 감사합니다. 난 그냥 free()메모리에 익숙해 : P
Oberon

3

k, 228

(,0){({(-7h$,/$2#x),2_x};@[;0;+;1];@[;0;-;1];{.[*;|2#x],2_x};{.[%;|2#x],2_x};
{.[+;|2#x],2_x};{.[-;|2#x],2_x};{.[xexp;|2#x],2_x};{.[mod;|2#x],2_x};{(*|x),-1_x};
{(1_x),*x};{(*x),x};{(2#x),x};{(|2#x),2_x};{,/(|2 2#x),4_x};1_)[y]x}/
0x01010b0c050c050b0905

8 4 6 2

비슷한 명령을 구현할 때 상당한 양의 반복이 이루어지며 아마도 어느 정도 엔지니어링 될 수 있습니다.


나는 내 사실과 똑같은 것을 계속 발견한다.
luser droog

3

924 882 622 603 587 569 562 자

명백한 줄 바꿈이 제거 된 상태 (가독성을 위해 유지됨).

#define A sbrk(8);signal(11,S);
#define W(x)write(1,x,1);
#define P (t>s?*--t:0)
#define U *t++
#define B(x,y)else if(b==(w=w+1 x)){w=P;y;U=w;}
*t,*s,w,a,d;char b;S(x){A}
p(x){if(x<0){W("-")x=-x;}if(x>9)p(x/10);b=48+x%10;W(&b)}
main(c){t=s=A U=0;
while(read(0,&b,1))if(!(w=47));
B(,w+=P*pow(10,w?ceil(log10(w)):1))
B(,++w)
B(,--w)
B(,w*=P)
B(,w=P/w)
B(,w+=P)
B(,w=P-w)
B(,w=pow(P,w))
B(,w=P%w)
B(,w=*s;memmove(s,s+1,t-s<<2))
B(+7,memmove(s+1,s,t++-s<<2);*s=w;w=P)
B(,U=w)
B(,a=P;U=a;U=w;U=a)
B(,a=P;U=w;w=a)
B(,a=P;c=P;d=P;U=a;U=w;U=c;w=d)
B(,w=P)
for(W("[")t>s;)p(P),W(" ")
W("]")}

이것은 Jan Dvorak의 의견에서 "언더 플로우 푸시 제로"해석을 구현합니다.

골프 버전은 실제로 Oberon의 정답 (환영) 압력 하에서 ungolfed 버전과 비교하여 실질적으로 변경되었습니다 .

... 체인 switch에 찬성 하여 진술 을 대체하면 내 경우의 모든 숫자를 인수 분해 할 수 있음을 알았습니다 . 대신 변수를 47로 초기화하여 한 번의 증분으로 48 (== ascii )로 증가시킨 다음 각 케이스 는 건너 뛸 때까지 증가 하여 어느 시점에서 가장 빈 첫 번째 매크로 인수를 사용하여 추가로 7을 추가합니다. 'A'로. ungolfed 버전은 않습니다 내가 가장 좋아 보여 /의 더 이상의 할당에 "무료"메모리를 얻기 위해 트릭을.ifelsew'0'w'A'sbrkSIGSEGV

#include<math.h>
#include<signal.h>
void S(int x){signal(SIGSEGV,S);sbrk(8*8*8);}
int*s,*t,*i,w,a,c,d;    //stack top index working accumulator count data
u(x){*t++=x;}           //push()
o(){return t>s?*--t:0;} //pop()
#define W(x)write(1,&x,1);  //output a byte
p(x){                   //print()
    if(x<0){    //negative?
        W(*"-") //output '-'
        x=-x;   //negate
    }
    if(x>9)     //more than one digit?
        p(x/10); //recurse after integer-divide
    b=48+x%10;   //isolate and convert single digit to ascii
    W(b)         //output ascii digit
}
main(){
    char b[1];
    signal(SIGSEGV,S);  //auto-allocate memory for stack
    t=s=sbrk(8*8*8);  //get start of memory and allocate
    while(read(0,b,1)){
        write(1,b,1); //for debugging: echo the command being executed
        switch(*b){
            case '0': w=o(); a=o(); for(c=ceil(log10(w));c>0;c--) a*=10; u(a+w); break;
            case '1': u(o()+1); break;
            case '2': u(o()-1); break;
            case '3': w=o(); u(o()*w); break;
            case '4': w=o(); u(o()/w); break;
            case '5': u(o()+o()); break;
            case '6': w=o(); u(o()-w); break;
            case '7': c=o();a=1; for(w=o();c>0;c--) a*=w; u(a); break;
            case '8': w=o(); u(o()%w); break;
            case '9': w=*s; memmove(s,s+1,4*(t-s-1)); t[-1]=w; break;
            case 'A': w=t[-1]; memmove(s+1,s,4*(t-s-1)); *s=w; break;
            case 'B': w=o(); u(w); u(w); break;
            case 'C': w=o(); a=o(); u(a); u(w); u(a); u(w); break;
            case 'D': w=o(); a=o(); u(w); u(a); break;
            case 'E': w=o(); a=o(); c=o(); d=o(); u(a); u(w); u(d); u(c); break;
            case 'F': o(); break;
        }
    }
    write(1,"\n[",2);   //dump the stack
    i=t;
    do {
        p(*--i);
    } while(i>s && write(1,",",1));
    write(1,"]\n",2);
}

쓰레기! 나는 연결에서 부정적인 것을 고려하지 않았습니다. 나는 log심지어 정의조차 없다고 생각한다 .
luser droog

골프 버전은 페이지 경계에 도달하면 처리 속도가 크게 느려지 며 처리기에서 8 바이트를 할당하고 메모리 액세스를 다시 시도하고 다시 8 회 반복하여 segfaulting 할 때까지 segfault를 반복적으로 수행합니다. 메모리가 유효 해집니다. ungolfed는 더 큰 상수를 사용하며 느려서는 안되지만 알고리즘은 동일합니다.
luser droog

1

R, 428 자

f=function(I){s=0;for(i in strsplit(I,"")[[1]]){r=s[-(1:2)];s=switch(i,'0'=c(as.integer(paste0(s[2],s[1])),r),'1'=c(s[1]+1,s[-1]),'2'=c(s[1]-1,s[-1]),'3'=c(s[1]*s[2],r),'4'=c(s[2]%/%s[1],r),'5'=c(s[1]+s[2],r),'6'=c(s[1]-s[2],r),'7'=c(s[2]^s[1],r),'8'=c(s[2]%%s[1],r),'9'=c(s[length(s)],s[-length(s)]),'A'=c(s[-1],s[1]),'B'=c(rep(s[1],2),s[-1]),'C'=c(rep(s[1:2],2),r),'D'=c(s[2:1],r),'E'=c(s[3:4],s[1:2],s[-(1:4)]),'F'=s[-1])};s}

들여 쓰기

f=function(I){
    s=0
    for(i in strsplit(I,"")[[1]]){
        r=s[-(1:2)]
        s=switch(i,
                '0'=c(as.integer(paste0(s[2],s[1])),r),
                '1'=c(s[1]+1,s[-1]),
                '2'=c(s[1]-1,s[-1]),
                '3'=c(s[1]*s[2],r),
                '4'=c(s[2]%/%s[1],r),
                '5'=c(s[1]+s[2],r),
                '6'=c(s[1]-s[2],r),
                '7'=c(s[2]^s[1],r),
                '8'=c(s[2]%%s[1],r),
                '9'=c(s[length(s)],s[-length(s)]),
                'A'=c(s[-1],s[1]),
                'B'=c(rep(s[1],2),s[-1]),
                'C'=c(rep(s[1:2],2),r),
                'D'=c(s[2:1],r),
                'E'=c(s[3:4],s[1:2],s[-(1:4)]),
                'F'=s[-1])
        }
    s
    }

실제로 :

> f('11BC5C5B95')
[1] 8 6 4 2

1

자바 스크립트, 685

골프 용이 아닌 버전 ( gist ) :

var Token = {
  Concatenate: '0',
  Increment: '1',
  Decrement: '2',
  Multiply: '3',
  Divide: '4',
  Add: '5',
  Subtract: '6',
  Exponent: '7',
  Modulus: '8',
  RotateRight: '9',
  RotateLeft: 'A',
  Duplicate: 'B',
  DoubleDuplicate: 'C',
  Swap: 'D',
  DoubleSwap: 'E',
  Delete: 'F'
};

function parse(input, mem) {
  var a, b, c, d;
  var stack = mem ? mem.slice() : [0];
  for (var i = 0, n = input.length; i < n; i++) {
    switch (input[i]) {
      case Token.Concatenate:
        a = stack.pop();
        b = stack.pop();
        stack.push(parseInt([b] + a));
        break;

      case Token.Increment:
        a = stack.pop();
        stack.push(a + 1);
        break;

      case Token.Decrement:
        a = stack.pop();
        stack.push(a - 1);
        break;

      case Token.Multiply:
        a = stack.pop();
        b = stack.pop();
        stack.push(b * a);
        break;

      case Token.Divide:
        a = stack.pop();
        b = stack.pop();
        stack.push(b / a | 0);
        break;

      case Token.Add:
        a = stack.pop();
        b = stack.pop();
        stack.push(b + a);
        break;

      case Token.Subtract:
        a = stack.pop();
        b = stack.pop();
        stack.push(b - a);
        break;

      case Token.Exponent:
        a = stack.pop();
        b = stack.pop();
        stack.push(Math.pow(b, a));
        break;

      case Token.Modulus:
        a = stack.pop();
        b = stack.pop();
        stack.push(b % a);
        break;

      case Token.RotateRight:
        a = stack.shift();
        stack.push(a);
        break;

      case Token.RotateLeft:
        a = stack.pop();
        stack.unshift(a);
        break;

      case Token.Duplicate:
        a = stack[stack.length - 1];
        stack.push(a);
        break;

      case Token.DoubleDuplicate:
        a = stack[stack.length - 1];
        b = stack[stack.length - 2];
        stack.push(b, a);
        break;

      case Token.Swap:
        a = stack.pop();
        b = stack.pop();
        stack.push(a, b);
        break;

      case Token.DoubleSwap:
        a = stack.pop();
        b = stack.pop();
        c = stack.pop();
        d = stack.pop();
        stack.push(b, a, d, c);
        break;

      case Token.Delete:
        stack.pop();
        break;

      default:
        throw new SynxtaxError('Invalid token "' + input[i] + '"');
    }
  }

  return stack.reverse();
}

exports.Token = Token;
exports.parse = parse;

골프 버전 :

function f(c){var b,d,e,f,a=[i=0],g=c.length;a.a=a.pop;for(a.b=a.push;i<g;i++)switch(c[i])
{case"0":b=a.a();a.b(parseInt([a.a()]+b));break;case"1":a[a.length-1]++;break;case"2":
a[a.length-1]--;break;case"3":a.b(a.a()*a.a());break;case"4":b=a.a();a.b(a.a()/b|0);break;
case"5":a.b(a.a()+a.a());break;case"6":b=a.a();a.b(a.a()-b);break;case"7":b=a.a();
a.b(Math.pow(a.a(),b));break;case"8":b=a.a();a.b(a.a()%b);break;case"9":a.b(a.shift());break;
case"A":a.a();a.unshift(a.a());break;case"B":a.b(a[a.length-1]);break;case"C":
a.b(a[a.length-2],a[a.length-1]);break;case"D":b=a.a();a.b(b,a.a());break;case"E":b=a.a();
d=a.a();e=a.a();f=a.a();a.b(d,b,f,e);break;case"F":a.a()}return a.reverse()}

예:

> f('11BC5C5B95')
[ 8, 6, 4, 2]

1

하스켈

import Data.List (elemIndex)

type Stack = [Integer]

u :: (Integer -> Integer) -> Stack -> Stack
u p (x:t) = p x : t -- unary operation

b :: (Integer -> Integer -> Integer) -> Stack -> Stack
b p (x:y:t) = p x y : t -- binary operation

encoding :: String
encoding = "$iv*/+-^%><dtsz."
-- encoding = "0123456789ABCDEF"

-- list of operations
ops :: [Stack -> Stack]
ops = [
 b (\x y -> read (show x ++ show y)),-- concatenation
 u (+1), -- increment
 u (subtract 1), -- decrement
 b (*), -- multiplication
 b div, -- division
 b (+), -- addition
 b (-), -- subtraction
 b (^), -- exponent
 b mod, -- modulus
 (\s -> last s : init s), -- rotate right
 (\(x:t) -> t ++ [x]), -- rotate left
 (\(x:t) -> x:x:t), -- duplicate
 (\(x:y:t) -> x:y:x:y:t), -- double duplicate
 (\(x:y:t) -> y:x:t), -- swap
 (\(x:y:x':y':t) -> x':y':x:y:t), -- double swap
 tail] -- pop

run :: String -> Maybe Stack
run code = run' code [0] where
  run' [] stack = Just stack
  run' (x:t) stack = elemIndex x encoding >>= run' t . ($stack) . (ops!!)

달리는

λ: run "diidt^svz"
Just [2,0,1,4]

"2014 챌린지에 관해서는 AF 작업으로 스택에서 0의 사본 만 얻을 수 있기 때문에 분명히 불가능합니다"-WAT? 0을 증가 시키면 0이 아닌 값이됩니다.
John Dvorak

@JanDvorak 그러나 증가를 위해서는 '1'을 써야합니다. 숫자는 금지되어 있습니다.

이것이 선택한 인코딩의 비극입니다. 문장 부호가 많은 세트 ( tr?로 표시 될 수 있음)를 매핑하면 가능합니다.
luser droog

1

커먼 리스프-589

공백없이 16 진수 입력을 허용합니다.

(setf w'(0))(defmacro u(&rest b)`(let((a(pop w))(b(pop w))),@b))(defmacro v(s)`(u(push(funcall ,s b a)w)))(setf i(list'(u(push(parse-integer(append(write-to-string b)(write-to-string a)))w))'(incf(car w))'(decf(car w))'(v #'*)'(v #'/)'(v #'+)'(v #'-)'(v #'expt)'(v #'%)'(let((a (car(last w))))(nbutlast w)(push a w))'(let((a(pop w)))(nconc w(list a)))'(push(car w)w)'(progn(push(cadr w)w)(push(cadr w)w))'(u(push a w)(push b w))'(u(push a(cdr(nthcdr 2 w)))(push b(cdr(nthcdr 2 w))))'(pop w)))(mapcar(coerce(read-line)'list)(lambda(a)(eval(nth(parse-integer(string a):radix 16)i)))(print w)

언 골프 드 :

(defparameter *stack* '(0))

(defmacro topvalues (&rest body)
    `(let ((top1 (pop *stack*))
           (top2 (pop *stack*))) ,@body))

(defmacro simple-op (opsym &rest body)
    `(topvalues 
        (push (funcall ,opsym top2 top1) *stack* )))

(defparameter *ops*
    (list
        ;concatenate
        '(topvalues
            (push 
                (parse-integer (append (write-to-string b) (write-to-string a)))
                *stack*))

        ;increment
        '(incf (first *stack*)) 

        ;decrement
        '(decf (first *stack*)) 

        ;multiply
        '(simple-op #'*)

        ;divide
        '(simple-op #'/)

        ;add
        '(simple-op #'+)

        ;subtract 
        '(simple-op #'-)

        ;exponent
        '(simple-op #'expt)

        ;modulus
        '(simple-op #'%)

        ;rotate right
        '(let ((a (car (last *stack*))))
            (nbutlast *stack*)
            (push a *stack*))

        ;rotate left
        '(let ((a (pop *stack*)))
            (nconc *stack* (list a)))

        ;duplicate
        '(push (first *stack*) *stack*)

        ;double duplicate
        '(progn 
            (push (second *stack*) *stack*)
            (push (second *stack*) *stack*))

        ;swap
        '(topvalues
            (push top1 *stack*)
            (push top2 *stack*))

        ;double swap
        '(topvalues 
            (push top1 (cdr (nthcdr 2 *stack*)))
            (push top2 (cdr (nthcdr 2 *stack*))))

        ;delete/pop
        '(pop *stack*)))

(mapcar 
(lambda (a)
    (eval (nth (parse-integer (string a) :radix 16) *ops*)))
(coerce (read-line) 'list))

1

PHP

가장 예쁘지는 않지만 작동합니다.

쉘에서 실행되며 파일 이름을 첫 번째 인수로 예상합니다. 그것은 3 가지 방언 중 하나를 받아들입니다.

음수 또는 누락 된 인덱스에 대해 정의되지 않은 동작

<?php
$f[0] = $f[48] = $f[36] = function(&$s){$v=array_shift($s);$s[0] .= $v;};
$f[1] = $f[49] = $f[105] = function(&$s){$s[0]++;};
$f[2] = $f[50] = $f[118] = function(&$s){$s[0]--;};
$f[3] = $f[51] = $f[42] = function(&$s){$v = array_shift($s); $s[0] *= $v;};
$f[4] = $f[52] = $f[47] = function(&$s){$v = array_shift($s); $s[0] = intval(floor($s[0] / $v));};
$f[5] = $f[53] = $f[43] = function(&$s){$v = array_shift($s); $s[0] += $v;};
$f[6] = $f[54] = $f[45] = function(&$s){$v = array_shift($s); $s[0] -= $v;};
$f[7] = $f[55] = $f[94] = function(&$s){$v = array_shift($s); $s[0] = pow($s[0], $v);};
$f[8] = $f[56] = $f[37] = function(&$s){$v = array_shift($s); $s[0] %= $v;};
$f[9] = $f[57] = $f[62] = function(&$s){$v = array_pop($s); array_unshift($s, $v);};
$f[10] = $f[65] = $f[60] = function(&$s){$v = array_shift($s); array_push($s, $v);};
$f[11] = $f[66] = $f[100] = function(&$s){array_unshift($s, $s[0]);};
$f[12] = $f[67] = $f[116] = function(&$s){$v = [$s[0], $s[1]]; array_unshift($s, $v[0], $v[1]);};
$f[13] = $f[68] = $f[115] = function(&$s){$v = $s[0]; $s[0] = $s[1]; $s[1] = $v;};
$f[14] = $f[69] = $f[122] = function(&$s){$v = $s[0]; $s[0] = $s[2]; $s[2] = $v; $v = $s[1]; $s[1] = $s[3]; $s[3] = $v;};
$f[15] = $f[70] = $f[46] = function(&$s){array_unshift($s);};

$stack = [0];
$file = fopen($argv[1], 'rb');
$size = filesize($argv[1]);
while($size--){
    $f[ord(fread($file, 1))]($stack);
}
fclose($file);
echo '['.implode(',',$stack)."]\n";

1

PureBasic- 2821 891 자

이것은 대화식 인터프리터입니다-파일이 없으며 0-9, AF로 주어진 코드를 입력하면 해당 명령이 실행되고 예제 포스트가 표시하는 것처럼 표시됩니다.

"X"또는 "Q"를 사용하여 종료하십시오.

이것은 정말 재미있었습니다 :)

Global NewList ProgramStack.q()
Global Num1.q, Num2.q

Macro Push(Value)
  LastElement(ProgramStack())
  AddElement(ProgramStack())
  ProgramStack() = Value
EndMacro

Macro Pop(Variable)
  LastElement(ProgramStack())
  Variable = ProgramStack()
  DeleteElement(ProgramStack())
EndMacro

Macro Peek(Variable)
  LastElement(ProgramStack())
  Variable = ProgramStack()
EndMacro

Push(0)

Procedure Concatenate()
  Pop(Num1)
  Pop(Num2)

  Push(Val( Str(Num2) + Str(Num1) ))
EndProcedure

Procedure Increment()
  LastElement(ProgramStack())
  ProgramStack() + 1
EndProcedure

Procedure Decrement()
  LastElement(ProgramStack())
  ProgramStack() - 1
EndProcedure

Procedure Multiply()
  Pop(Num1)
  Pop(Num2)

  Push( Num2 * Num1 )
EndProcedure

Procedure Divide()
  Pop(Num1)
  Pop(Num2)

  Push( Num2 / Num1 )
EndProcedure

Procedure Add()
  Pop(Num1)
  Pop(Num2)

  Push( Num2 + Num1 )
EndProcedure

Procedure Subtract()
  Pop(Num1)
  Pop(Num2)

  Push( Num2 - Num1 )
EndProcedure

Procedure Exponent()
  Pop(Num1)
  Pop(Num2)

  Push( Pow(Num2, Num1) )
EndProcedure

Procedure Modulus()
  Pop(Num1)
  Pop(Num2)

  Push( Mod(Num2, Num1) )
EndProcedure

Procedure RotateRight()
  FirstElement(ProgramStack())
  Num1 = ProgramStack()
  DeleteElement(ProgramStack(),1)
  Push(Num1)
EndProcedure

Procedure RotateLeft()
  Pop(Num1)
  FirstElement(ProgramStack())
  InsertElement(ProgramStack())
  ProgramStack() = Num1
EndProcedure

Procedure Duplicate()
  Peek(Num1)
  Push(Num1)
EndProcedure

Procedure DoubleDuplicate()
  Pop(Num1)
  Pop(Num2)
  Push(Num2)
  Push(Num1)
  Push(Num2)
  Push(Num1)
EndProcedure

Procedure SingleSwap()
  Pop(Num1)
  Pop(Num2)
  Push(Num1)
  Push(Num2)
EndProcedure

Procedure DoubleSwap()
  Protected Num3.q, Num4.q
  Pop(Num1)
  Pop(Num2)
  Pop(Num3)
  Pop(Num4)
  Push(Num2)
  Push(Num1)
  Push(Num4)
  Push(Num3)
EndProcedure

Procedure Delete()
  Pop(Num1)
EndProcedure

OpenConsole()
EnableGraphicalConsole(1)

Position = 0
Repeat
  ConsoleLocate(Position, 0)

  e.s = UCase( Inkey() )

  Select e
    Case "0"
      Concatenate()
    Case "1"
      Increment()
    Case "2"
      Decrement()
    Case "3"
      Multiply()
    Case "4"
      Divide()
    Case "5"
      Add()
    Case "6"
      Subtract()
    Case "7"
      Exponent()
    Case "8"
      Modulus()
    Case "9"
      RotateRight()
    Case "A"
      RotateLeft()
    Case "B"
      Duplicate()
    Case "C"
      DoubleDuplicate()
    Case "D"
      SingleSwap()
    Case "E"
      DoubleSwap()
    Case "F"
      Delete()
  EndSelect

  If e <> ""
    Print(e)
    ConsoleLocate(Position, 1)
    Print("|")
    yLoc.i = ListSize(ProgramStack()) + 1

    ForEach ProgramStack()
      ConsoleLocate(Position, yLoc)
      Print(Str(ProgramStack()))
      yLoc - 1
    Next

    Position + 2
  EndIf
Until e = "X" Or e = "Q"

편집 : 수면 후, 나는 골프를 쳤다고 생각했습니다-참조 용으로 읽을 수있는 버전을 남겼습니다.

Q 또는 X를 종료하고 종료하기 위해 창을 닫는 것을 제외하고는 모두 동일하게 작동합니다.

NewList S()
Macro P
Print
EndMacro
Macro G
ConsoleLocate
EndMacro
Macro LE
LastElement(S())  
EndMacro
Macro U(V)
LE
AddElement(S())
S()=V
EndMacro
Macro O(V)
LE
V=S()
DeleteElement(S())
EndMacro
U(0)
OpenConsole()
EnableGraphicalConsole(1)
X=0
Repeat
G(X,0)
e.s=UCase(Inkey())
Select e
Case"0"
O(H)
O(J)
U(Val(Str(J)+Str(H)))
Case"1"
LE
S()+1
Case"2"
LE
S()-1
Case"3"
O(H)
O(J)
U(J*H)
Case"4"
O(H)
O(J)
U(J/H)
Case"5"
O(H)
O(J)
U(J+H)
Case"6"
O(H)
O(J)
U(J-H)
Case"7"
O(H)
O(J)
U(Pow(J,H))
Case"8"
O(H)
O(J)
U(Mod(J,H))
Case"9"
FirstElement(S())
H=S()
DeleteElement(S(),1)
U(H)
Case"A"
O(H)
FirstElement(S())
InsertElement(S())
S()=H
Case"B"
O(H)
U(H)
U(H)
Case"C"
O(H)
O(J)
U(J)
U(H)
U(J)
U(H)
Case"D"
O(H)
O(J)
U(H)
U(J)
Case"E"
O(H)
O(J)
O(K)
O(L)
U(J)
U(H)
U(L)
U(K)
Case"F"
O(H)
EndSelect
If e<>""
P(e)
G(X,1)
Y=ListSize(S())+1
ForEach S()
G(X,Y)
P(Str(S()))
Y-1
Next
X+2
EndIf
ForEver

1

커먼 리스프-586

(defmacro n(s)(with-gensyms($)(labels((?()`(pop,$))(!(x)`(push,x,$))(@(~)(!(list ~(?)(?))))(r@(~)(@`(lambda(x y)(,~ y x)))))`(let((,$`(,0))),@(loop for p below(length s)collect(case(parse-integer s :start p :end(1+ p):radix 16)(0(@'(lambda(a b)(+(* a(expt 10(if(> b 0)(ceiling(log b 10))1)))b))))(1`(incf(car,$)))(2`(decf(car,$)))(3(@'*))(4(@'/)) (5(@'+))(6(@'-))(7(r@'expt))(8(r@'mod))(9`(setf,$(#1=rotate,$)))(10`(setf,$(#1#,$ -1)))(11`(push(car,$),$))(12`(setf,$(nconc(#2=subseq,$ 0 2),$)))(13`(reversef(#2#,$ 0 2)))(14`(setf,$(append(#1#(#2#,$ 0 4)2)(#2#,$ 4))))(15`(pop,$)))),$))))

언 골프

매크로로 확장 된 코드에서 새로운 스택을 사 전적으로 바인딩합니다. 전역 변수에 대한 참조는 없습니다. 또한 머신 코드로 컴파일됩니다.

(ql:quickload :alexandria)
(mapc #'use-package '(cl alexandria))
(defmacro n(s)
  (with-gensyms($)
    (labels ((?()`(pop,$))
             (!(x)`(push,x,$))
             (bop(op)(!(list op(?)(?))))
             (rbop(op)(bop`(lambda(x y)(,op y x)))))
      `(let((,$`(,0)))
         ,@(loop for p below(length s)
                 collect(case(parse-integer s :start p :end(1+ p):radix 16)
                           (#x0(bop'(lambda(a b)(+(* a(expt 10(if(> b 0)(ceiling(log b 10))1)))b))))
                           (#x1`(incf(car,$)))                    
                           (#x2`(decf(car,$)))
                           (#x3(bop'*))                    
                           (#x4(bop'/))
                           (#x5(bop'+))                    
                           (#x6(bop'-))
                           (#x7(rbop'expt))
                           (#x8(rbop'mod))
                           (#x9`(setf,$(rotate,$)))
                           (#xA`(setf,$(rotate,$ -1)))
                           (#xB`(push(car,$),$))
                           (#xC`(setf,$(nconc(subseq,$ 0 2),$)))
                           (#xD`(reversef(subseq ,$ 0 2)))
                           (#xE`(setf,$(append(rotate(subseq,$ 0 4)2)(subseq,$ 4))))
                           (#xF`(pop,$))))
         ,$))))

   (n "11bc5c5b95")
   => macroexpands into (8 6 4 2)

1

파이썬 2, 508 바이트

s,d=[0],lambda:s.pop(1)
for C in raw_input():
 D=int(C,16)
 if D<1:s[0]=int(`s[0]`+`d()`)
 if D==1:s[0]+=1
 if D==2:s[0]-=1
 if D==3:s[0]*=d()
 if D==4:s[0]=d()/s[0]
 if D==5:s[0]+=d()
 if D==6:s[0]-=d()
 if D==7:s[0]=d()**s[0]
 if D==8:s[0]=d()%s[0]
 if D==9:s=s[-1:]+s[:-1]
 if D==10:s=s[1:]+s[:1]
 if D==11:s=s[:1]+s
 if D==12:s=s[0:2]+s
 if D==13:s=s[1:2]+s[:1]+s[2:]
 if D==14:s=s[2:4]+s[0:2]+s[4:]
 if D>14:s=s[1:]
print s

"0123456789ABCDEF"인코딩을 사용합니다. 나는 이것이 어떻게 나타 났는지 정말로 자랑스럽게 생각합니다. 파일을 읽지 않고 STDIN에서 입력을 얻지 만 문제가 있으면 쉽게 변경할 수 있습니다.

2014 년 문제에 대한 2 가지 해결책 :

B11CB3A1AED0A00( 16 15 바이트)-일반 연결기.

BB102CD11B513B3622E( 20 19 바이트)-훨씬 쿨러-(5 * (10-1)) ^ 2-11로 평가


0

파이썬 2, 955 바이트

import sys
global s
s=[0]
c=lambda x: x.append(str(x.pop())+str(x.pop()))
i=lambda x: x.append(x.pop()+1)
v=lambda x: x.append(x.pop()-1)
x=lambda x: x.append(x.pop()*x.pop())
q=lambda x: x.append(x.pop(-2)/x.pop())
a=lambda x: x.append(x.pop()+x.pop())
w=lambda x: x.append(x.pop(-2)-x.pop())
e=lambda x: x.append(x.pop(-2)**x.pop())
m=lambda x: x.append(x.pop(-2)%x.pop())
r=lambda x: x.append(x.pop(0))
l=lambda x: x.insert(0,x.pop())
d=lambda x: x.append(x[-1])
t=lambda x: x.extend(x[-2:])
s=lambda x: x.insert(-2,x.pop())
def z(x):
    for y in [0,1]:
        s.insert(-3,s.pop())
k={'$':c,'i':i,'v':v,'*':x,'/':q,'+':a,'-':w,'^':e,'%':m,'>':r,'<':l,'d':d,
   't':t,'s':s,'z':z,'.':lambda x: x.pop()}
if __name__=='__main__':
    with open(sys.argv[1],'r') as f:
        while 1:
            b=f.read(1)
            if not b or b not in k.keys():
                break
            else:
                n=k[b](s)
                for x in s: print s,

각 기능의 기능

  • c : 연결 ($)
  • i : 증분 (i)
  • v : 감소 (v)
  • x : 곱하기 (*)
  • q : 나누기 (/)
  • a : 추가 (+)
  • w : 빼기 (-)
  • e : 지수 (^)
  • m : 모듈로 (%)
  • r : 오른쪽 이동 (>)
  • l : 왼쪽 시프트 (<)
  • d : 복제 (d)
  • t : 두 번 복제 (t)
  • s : 상위 2 개 값 교환
  • z : 이중 스왑 (z)

이것이 코드 골프가 아니며 ( 인기 경연 대회 인 ) 코드가 거의 골프가 아니기 때문에 바이트 수를 포함시킬 필요는 없다고 생각합니다.
FlipTack

@FlipTack 누군가 알고 싶어하기 때문에 바이트 수만 포함합니다.
ckjbgames
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.