Stackylogic 실행


45

Stackylogic 난에 그 인출 구성된 로직 기반의 프로그래밍 언어 0의과 1입력의를 단일 출력 0또는 1시 완료.

Stackylogic 프로그램은 세 개의 문자 만 포함 할 수있는 행으로 구성되며 한 행 의 끝에 01?정확히 한 문자 만 포함 <됩니다. 라인은 비워 둘 수 없습니다 수 있으며, 함께 라인은 <적어도 하나 있어야합니다 0, 1또는 ?그 전에합니다.

다음 은 두 비트 의 NAND 를 계산하는 샘플 프로그램입니다 .

1
?<
11
?
0

Stackylogic 프로그램의 모든 행은 스택 으로 간주 되며 맨 아래는 왼쪽, 맨 위는 오른쪽입니다. 암시 적으로 프로그램의 첫 번째 줄 앞과 마지막 줄 뒤에 빈 스택 (빈 줄)이 있습니다.

<, 우리가 전화 할게있는 커서를 Stackylogic 프로그램이 실행될 때, 마크 스택에 시작합니다. Stackylogic 프로그램의 실행은 다음과 같이 진행됩니다.

  1. 커서가 현재 가리키는 스택에서 맨 위 문자를 팝하십시오.

    • 문자가 ?인 경우 사용자에게 a 0또는 a 1를 묻고 문자 인 것처럼 행동하십시오.
    • 문자가 0인 경우 커서를 한 스택 위로 움직입니다 (현재 줄 위의 줄로).
    • 문자가 1인 경우 커서를 한 스택 아래로 (현재 줄 아래의 줄로) 이동하십시오.
  2. 커서가 이동하는 스택이 비어 있으면 스택에서 마지막으로 튀어 나온 마지막 값 (항상 a 0또는 1)을 출력하고 프로그램을 종료하십시오.

  3. 그렇지 않으면, 커서가 이동하는 스택이 비어 있지 않으면 1 단계로 돌아가서 프로세스를 반복하십시오.

Stackylogic 프로그램은 결국 스택을 고갈시켜야하기 때문에 항상 종료됩니다.

낸드 예

NAND 프로그램에서 커서는 다음에서 시작됩니다 ?.

1
?<
11
?
0

우리는 1일단 사용자 입력 ?이 팝업되면 커서가 아래로 이동하여 프로그램이 다음과 같이 표시된다는 것을 가정합니다 .

1

11<
?
0

이제 1커서 스택의 맨 위에 평원 이 있습니다. 정식으로 팝업되고 커서가 다시 이동합니다.

1

1
?<
0

이제 사용자 입력 가정 0?커서가 이동을 의미합니다 :

1

1<

0

다시 a 1는 커서 스택에 있으므로 커서가 튀어 나와 아래로 이동합니다.

1


<
0

마지막으로 커서 스택이 비어 있으므로 마지막으로 터진 값인 1,이 출력되고 프로그램이 종료됩니다.

이는은 NAND 게이트에 대한 정확 1 NAND 0하다 1. 이것은 물론 확인해야 할 경우 다른 세 개의 2 비트 입력에 적용됩니다.

또는 예

이 Stackylogic 프로그램은 OR 게이트를 시뮬레이션합니다 .

?
?<

초기 입력은 1커서를 마지막 행 아래의 암시 적 빈 스택으로 푸시하여 프로그램을 종료하고 1방금 입력 한 것을 출력한다는 것을 쉽게 알 수 있습니다.

00반면에 입력의 경우, 커서는 상단의 암시 적 빈 스택으로 이동하여 프로그램을 종료하고 마지막 0입력을 출력합니다 .

도전

인쇄하거나 결과를 반환하는 문자열로 Stackylogic 프로그램에 받아 그것을 실행되는 프로그램 또는 기능을 작성 0또는 1.

?의, 당신은에 대한 사용자를 묻는 메시지를 표시 할 수 있습니다 0또는 1입력, 또는 미리 설정된 문자열에서 값을 읽을 수 0의 그리고 1당신은 또한 입력으로 취하는 것이의. (이것은 프로그램 / 함수에 다른 문자열 입력이 될 수 있거나 프로그램 문자열의 첫 번째 또는 마지막 줄이 입력 스트림이라고 가정 할 수 있습니다).

프로그램과 입력이 항상 잘 구성되어 있다고 가정 할 수 있습니다. 선택적으로 입력 프로그램에 하나의 후행 줄 바꿈이 있다고 가정 할 수 있습니다 (그러나 끝에는 항상 암시 적 빈 스택이 있음을 기억하십시오).

바이트 단위의 가장 짧은 코드가 이깁니다.

더 많은 샘플 프로그램

ZERO
0<

ONE
1<

BUFFER
?<

NOT
1
?<
0

AND
?<
?

NAND
1
?<
11
?
0

OR
?
?<

NOR
1
?
00
?<
0

XOR(v1)
?
0
1?<
?
0

XOR(v2)
?
?<
11
?
0

XNOR(v1)
1
?
0?<
1
?

XNOR(v2)
1
?
00
?<
?

MEDIAN(v1)
1
???<
0

MEDIAN(v2)
?
1?<
??

중간 프로그램에 대한 Martin 감사 합니다 .


3- 입력 함수를 추가하려는 경우 다음과 같은 중간 값을 구현하는 방법이 ?\1?<\??있습니다. 또는 대칭형 5 라인 구현이 있습니다.?\?0\?<\?1\?
Martin Ender

아, 더 깔끔한 구현을 발견했습니다 1\???<\0.
Martin Ender

2
@MartinEnder의 3- 입력 중간 함수 (대다수 규칙 함수)를 깔끔하게 구현하면 일반적으로 훌륭하게 나타납니다. 예를 들어, 7- 입력 과반수 규칙 함수는 111\???????<\000입니다.
Greg Martin

Stackylogic 프로그램 $ P $의 "bizarro"를 원래 프로그램의 행 순서를 반대로하고 1을 0으로 바꾸고 그 반대로 바꾸면 (하지만? s와 <은 그대로 두는) 프로그램 $ BP $가됩니다. 입력 값 $ b_1, b_2, \ dots $에 대한 $ BP $의 출력은 입력 값 $! b_1,! b_2, \ dots $에 대한 $ P $ 출력의 NOT이 아닙니다. 주어진 AND 및 OR 구현은 NAND 및 NOR 및 XOR / XNOR의 두 가지 버전과 같이이 방식으로 기괴하게 관련됩니다. 일부 프로그램은 자체 기괴한 프로그램입니다 (BUFFER, NOT, MEDIAN (v1)).
Greg Martin

1
@GregMartin Yep. 나는 기술 용어가 이중성 이라고 생각합니다 .
Calvin 's Hobbies

답변:


15

망막 , 79 78 73 68 66 65 63 62 55 44 바이트

바이트 수는 ISO 8859-1 인코딩을 가정합니다.

+`(.)([^_]*)\?<|(¶.*)0<|1<(¶.+)
$2$1$4<$3
1<

입력은 STDIN을 통해 이루어지며 소스 코드에서 두 개의 줄 바꿈으로 구분 된 사용자 입력이어야합니다.

온라인으로 사용해보십시오! (처음 두 줄은 테스트 모음을 활성화합니다. 여기서 각 줄은 /줄 바꿈 대신 별도의 테스트 사례입니다 .)

나는 여기에서 무슨 일이 있었는지 완전히 확신하지 못한다. 이것은 정말 어수선한 해결책처럼 느껴지며 실제로 Retina가 만든 문제는 아니지만 어떤 이유로 든 현재의 모든 대답을 여전히 능가합니다.

설명

이것의 최종 버전은 실제로 상당히 단순했습니다.

+`(.)([^_]*)\?<|(¶.*)0<|1<(¶.+)
$2$1$4<$3

첫 번째 단계는 +언어의 실제 해석을 수행 하는 루프 ( 옵션 으로 인해) 일뿐 입니다. 이 단계는 단일 정규식 대체이지만 실제로는 사용하지 않는 분기에서 그룹을 캡처하는 것이 대체 중에 빈 것으로 간주된다는 사실을 이용하여 실제로 한 단계로 짜인 세 가지 다른 대체입니다.

  1. 가공 ?:

    (.)([^_]*)\?<
    $2$1<
    

    이것은 단순히 입력의 첫 번째 문자를 취한 다음을 찾을 때까지 임의의 문자를 일치 ?<시키고 첫 번째 문자를 앞에 놓습니다 <( ?).

  2. 가공 0:

    (¶.*)0<
    <$1
    

    이것은 a 앞에 오는 행과 일치 0<하고을 <제거 0합니다. (효과적으로 이것은 단지 삭제 0하고 <한 줄을 위로 이동시킵니다 .)

  3. 가공 1:

    1<(¶.+)
    $1<
    

    <를 삭제하는 동안 한 줄 아래로 이동한다는 점을 제외하고는 거의 동일 합니다 1. 주목해야 할 중요한 세부 사항 중 하나는을 +대신 사용하는 것입니다 *. 즉, 다음 줄은 비워 둘 필요가 없습니다.

흥미로운 부분은 이것이 왜 작동하는지 그리고 왜 최종 출력을 결정하기 위해 우리가 팝한 마지막 값을 추적 할 필요가 없는지 알아내는 것입니다. 이를 위해서는 위의 루프가 어떻게 종료 될 수 있는지 고려해야합니다. 가능한 모든 일치 항목이 문자열을 변경하므로 (적어도 하나의 문자가 삭제되므로) 일치하지 않는 경우 만 고려하면됩니다.

앞의 문자가있는 경우 <입니다 ?일치가 실패 할 수있는 유일한 방법은 그것의 앞에 비 라인 피드 문자 어디서나이되지 않는 것입니다,하지만 우리는 항상 충분한 입력이 있다고 보장하고 있기 때문에 그런 일이 없습니다.

앞의 문자 경우 <IS는 0항상 (소스 코드 입력을 분리 빈 줄을 수 있음) 현재 위의 또 다른 라인이 이후, 정규 표현식은 항상 일치합니다.

앞에있는 문자 <1인 경우 마지막 줄에 있거나 (일치하지 않기 때문에 ) 다음 줄이 비어있는 경우 (일치하지 않기 때문에) 정규식이 실패합니다 .+. 이 두 경우 모두 a를 팝한 후 프로그램을 종료하는 것에 해당합니다 1.

마지막으로 <앞에 오지 않는 가능성도 있습니다 ?01. a를 띄우고 0빈 줄로 올라 가야만이 상황에 도달 할 수 있으며 , 그 <앞에는 줄 바꿈이 있습니다.

프로그램이에 종료 때, 1의는 <여전히 그 후가 될 것입니다 1. 그러나 프로그램이에서 종료 0되면 빈 줄로 이동했을 것입니다. 간단한 일치 단계를 통해이 정보를 원하는 출력으로 쉽게 전환 할 수 있습니다.

1<

이것은 단순히 1<문자열에서 일치하는 것을 계산 합니다. 위의 이유에 1의해 프로그램이에서 종료 된 경우 1및에서 0종료 된 경우 0입니다.


3
당신은 마법사입니다.
GamrCorps

그런 정규식 Mch Wow
Rohan Jhunjhunwala

12

볼록 , 102 95 바이트

글쎄, 스택 기반 언어로 코딩 된 스택 목록 기반 언어는 상당히 어려운 것으로 판명되었습니다. 내 말을 표시하십시오 : 나는 이것을 100 바이트 이하로 만들 것입니다! 편집 : 성공!

N/S\+{s)_'<={R:M;}{R):R;+}?}%'<-M){(æ=)s_:Q;"?10 ""l+ M):M; M(:M; W:M;A~p"S/Ë~~_!S*+tM)Q:A;}h;;

온라인으로 사용해보십시오!

프로그램 입력은 명령 행 인수를 통해 이루어집니다. 일반적으로 0s 및 1s를 입력 합니다 (TIO에서는 "입력"상자에서 줄 바꿈으로 구분됨).


설명:

모든 코드는 세 부분으로 나눌 수 있습니다.

N/S\+

이 비트는 단순히 입력 프로그램을 가져 와서이를 배열의 행으로 변환하고 배열의 " "시작 부분에 행을 추가합니다 . Convex의 배열이 래핑되므로 빈 스택 만 시작하면됩니다.

{s)_'<={R:M;}{R):R;+}?}%'<-

이 부분은 실행할 라인 (또는 스택)을 결정합니다. 각 줄을 검색하여 올바른 스택 번호를 M변수에 넣습니다 .

M){(æ=)s_:Q;"?10 ""l+ M):M; M(:M; W:M;A~p"S/Ë~~_!S*+tM)Q:A;}h;;

이것은 재미있는 비트입니다! 공백 ( " ") 만있는 줄에 도달 할 때까지 계속 반복 됩니다 (빈 스택을 상징합니다). 줄이 비어 있지 않으면 다음을 수행합니다.

  1. 스택에서 마지막 문자를 팝합니다.
  2. 스위치 문 :
    1. 문자가 인 경우 ?입력을 받아 해당 문자를 줄에 추가하십시오.
    2. 문자가 인 경우 0선 포인터를 위로 이동하십시오.
    3. 문자가 인 경우 1선 포인터를 아래로 이동하십시오.
    4. 문자가 (공백) 인 경우 가장 최근에 팝업 된 항목을 인쇄하고 프로그램을 종료하십시오.

6

32 비트 x86 머신 코드, 70 바이트

16 진수로 :

FC89E1565F31D28A07A8DF740B3C3C7511428D5C24FCEB0A5729142484C07405B20147EBE2578B3B8A17F6C2DF7414FF0B923C3F7501AC3C30750383C30883EB04EBE389CCC3

입력은 ESI를 통해 전달되는 NULL로 끝나는 여러 줄 문자열 (줄 바꿈)입니다. 사용자 입력은 첫 번째 줄로 가정됩니다. AL에서 '0'/ '1'을 반환합니다.

분해 :

fc           cld
89 e1        mov    ecx,esp
56           push   esi
5f           pop    edi                  ;EDI=ESI
31 d2        xor    edx,edx              ;EDX=0
_loop0:
8a 07        mov    al,BYTE PTR [edi]    ;AL=*EDI
a8 df        test   al,0xf5              ;AL&~0x0a==0 => separator ('\n' or '\0')
74 0b        je     _stck
3c 3c        cmp    al,'<'
75 11        jne    _loop0end
42           inc    edx                  ;For "cursor" symbol adjust stack pointer offset
8d 5c 24 fc  lea    ebx,[esp-0x4]        ;and load EBX with the address where this pointer
eb 0a        jmp    _loop0end            ;is going to be stored in the next iteration
_stck:
57           push   edi                  ;Pointer to the separator
29 14 24     sub    DWORD PTR [esp],edx  ;adjusted to point to the top of the stack
84 c0        test   al,al                ;AL==0?
74 05        je     _loop0break          ;break
b2 01        mov    dl,0x1               ;EDX can be [0..2], resets to 1
_loop0end:
47           inc    edi                  ;++EDI
eb e2        jmp    _loop0
_loop0break:
57           push   edi                  ;*EDI==0, add lower implicit empty stack
_loop1:                                  ;The actual state machine code
8b 3b        mov    edi,DWORD PTR [ebx]  ;EDI=*EBX
8a 17        mov    dl,BYTE PTR [edi]    ;DL=*EDI
f6 c2 df     test   dl,0xf5              ;DL&~0x0a
74 14        je     _loop1break          ;ZF==1 => current stack is empty
ff 0b        dec    DWORD PTR [ebx]      ;--(*EBX): pop the stack
92           xchg   edx,eax              ;AL=DL
3c 3f        cmp    al,'?'
75 01        jne    _skplods             ;AL=='?' => substitute char from the input string
ac           lodsb
_skplods:
3c 30        cmp    al,'0'
75 03        jne    _0x31                ;EBX+=AL==0?4:-4
83 c3 08     add    ebx,0x8              ;But to avoid wasting 2 bytes for the jump after the 'add'
_0x31:                                   ;add 8 and fall through to subtract 4 back
83 eb 04     sub    ebx,0x4
eb e3        jmp    _loop1
_loop1break:
89 cc        mov    esp,ecx              ;Clear the stack
c3           ret                         ;Returns '0'/'1' in AL

5

자바 스크립트 (ES6), 136 (138)

프로그램에서 종료 줄 바꿈 가정

(p,i,j=0)=>eval("for(p=`\n${p}`.split`\n`.map((x,i)=>((c=(x=[...x]).pop())=='<'?k=i:x.push(c),x));a=p[k].pop();k-=1-c-c)c=1/a?a:i[j++]")

덜 골프

(p, i, j=0)=>{
  p=`\n${p}`
     .split`\n`
     .map(
       (x,i)=>
       (
         x = [...x],
         c = x.pop(),
         c == '<' ? k=i : x.push(c),
         x
       )
     )
  for(; a = p[k].pop(); k -= 1-c-c)
    c = 1/a ? a : i[j++];
  return c;
}

테스트

F=(p,i,j=0)=>eval("for(p=`\n${p}`.split`\n`.map((x,i)=>((c=(x=[...x]).pop())=='<'?k=i:x.push(c),x));a=p[k].pop();k-=1-c-c)c=1/a?a:i[j++]")

function run() {
  var pgm=P.value+'\n'
  var i=I.value
  O.textContent = F(pgm,i)
}

run()
#P { width:60%; height: 6em }
#I { width:50%;  }
Program<br>
<textarea id=P>1
?&lt;
11
?
0</textarea><br>
Input<br>
<input id=I value=01>
<button onclick='run()'>Run</button>
<br>Output
<pre id=O></pre>



2

파이썬 3 147 146 145 144 바이트

@Lynn 덕분에 1 바이트.

def f(p):
 i=p[:p.find("<")].count("\n");p=p.split()
 try:
  while 1:*p[i],c=p[i];c=c>"<"and input()or c;i+=c<"<"and int(c)*2-1
 except:return c

1

파이썬 3, 318

def s(f,z):
 p=b="";g=0;a=[];n=a.append;n(p)
 for i in f:
  if i=="\n":n(p);p=''
  else:p+=i
 n(p);p=b;n(p)
 while g<len(a):
  if'<'in a[g]:q=g;a[q]=a[q][:-1]
  g+=1
 while 1:
  v=a[q]
  if v=='':print(b);break
  if v[-1]=='1':a[q]=v[:-1];q+=1;b=1
  elif v[-1]=="0":a[q]=v[:-1];q-=1;b=0
  else:a[q]=v[:-1]+z[0];z=z[1:]

F는 프로그램이고 z는 입력입니다. 예, 변수 이름이 제정신입니다.


1

ES6, 190 바이트

f=(p,i)=>{
n=p.split`<`[0].split`\n`.length-1
p=p.split`\n`.map(o=>o.split``)
i=i.split``
p[n].pop()
while(p[n]&&p[n].length){
c=p[n].pop()
v=c=='?'?i.shift():Number(c)
n+=v*2-1
}
return v
}

처럼 사용 f(program, input)


2
몇 가지 일반적인 골프 팁 (어딘가에있는 목록이 있습니다) : [...o]대신에 o.split``사용하고 for대신에 사용하여 while두 표현식을 for절약 2 바이트 로 이동할 수 있습니다 . 몇 가지 구체적인 팁 : 나는 당신을 위해 Number캐스팅 할 *2것이므로 캐스팅이 불필요 하다고 생각 하고 i사용하여 읽고 11 바이트를 절약한다고 생각합니다. j=0i[j++]
Neil

1
당신은 필요가 없습니다 f=, 익명의 기능을 사용할 수 있습니다.
gcampbell

0

자바 256 255 231 219 215 213 바이트

int f(char[][]p,char[]I){int l=p.length,d=0,j=-1,c=0,k=0,i[]=new int[l];while(++j<l)if(p[j][i[j]=p[j].length-1]==60)i[k=j]--;try{for(;;k+=c>48?1:-1)c=(c=p[k][i[k]--])>49?I[d++]:c;}catch(Throwable t){}return c-48;}

이데온 데모.

프로그램과 입력을 인수로 받아서 결과를 정수로 리턴합니다.


@LeakyNun for루프로 변경 되었지만 첫 번째 코멘트의 의미는 무엇입니까?
PurkkaKoodari

@ Pietu1998 LeakyNun은 가능 int f(String[]I)...하고 피할 수 있음을 의미합니다 .String[]p=I.split("\n");
cat

함수를 다음과 같이 선언 할 수 있음을 의미합니다.int f(String[]P)
Leaky Nun

1
@cat ninja'd 7 초 : /
Leaky Nun

또한 Java 8에 정착하면 다음과 같은 람다를 가질 수 있습니다.->(String[]I){...
cat

0

PHP (<7.0), 195192 바이트

프로그램을 첫 번째 인수로 사용하고 각 값을 추가 인수로 사용합니다.
줄 바꿈이 아닌 split ( "", ..) asn 공백으로 이것을 테스트했지만 어쨌든 작동해야합니다.
php> 5.3에서 실행할 경우 사용되지 않는 통지를 제공합니다.
또한 프로그램 상단을 벗어나면 경고가 표시됩니다. 그러나 여전히 제대로 작동하고 출력되므로 괜찮습니다.

<?php foreach(split("\n",$argv[++$t])as$l)$p[]=str_split($l);for($i=-1;end($p[++$i])!='<';);array_pop($p[$i]);for(;($v=array_pop($p[$i]))!==null;$i+=$n?:-1)($n=$v)=='?'&&$n=$argv[++$t];echo$n;

0

C, 264 249 244 242

C는 문자열 조작과 잘 어울리지 않지만 꽤 짧습니다.

커서 ( <) 의 문자열을 스캔하고 1 자리 뒤로 이동하고 명령을 읽고 tab문자로 바꾸고 한 줄 앞으로 또는 뒤로 이동하여 작동합니다. char array[]="1\n?<\n11\n?\n0";result = f(array);캐리지 리턴도 허용되지만 입력은 C 문자 배열 형식입니다 .

입력 문자열이 수정되었지만 길이는 변경되지 않습니다.

t;f(char*n){char*p=strchr(n,60);for(*p--=9;;){if(*p==63)scanf("%d",&t),*p=t+48;if(*p^49){for(*p--=9;p>n&&*p^10;--p);for(--p;p>n&&*p==9;--p);if(p<n||*p==10)return 0;}else{for(*p++=9;*p&&*p^10;++p);for(p+=!!*p;*p>10;++p);if(*--p<11)return 1;}}}

테스트 프로그램

줄 바꿈 대신 단일 백 슬래시를 사용하여 각 테스트 케이스와 함께이 프로그램을 별도의 매개 변수로 실행하십시오. 테스트 사례는 빈 줄로 구분됩니다.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, const char **argv)
{
    while (*++argv)
    {
        char *input=malloc(strlen(*argv)+1),*p;
        strcpy(input,*argv);
        printf("testing %s\n",input);
        for (p=input;*p;++p)
            if (*p=='\\')
                *p=10;
        printf("result: %d\n\n",f(input));
        free(input);
    }
    return 0;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.