합산? 그건 내 장점이야!


18

소개

Forte 는 숫자 값을 수정한다는 개념에 기반한 매우 독특한 난해한 언어입니다. Forte 숫자는 상수가 아니라 변수에서 LET명령어를 사용하여 새 값을 지정할 수 있습니다.

예를 들어, LET 2=4-1지금 부터 실행 한 후에 2는 값 을 가정합니다. 3즉, 값 2이 표현식에 나타날 때마다 값 이 대신 "대체"됩니다 3. 이제식이로 (1+1)*2평가됩니다 9.

Forte의이 명령어는 정보 저장 및 흐름 제어에 사용됩니다 (행 번호가 매겨지고 번호 값을 변경하여 실행 순서를 결정할 수 있음). 이 도전에서 우리는이 두 번째 측면을 다루지 않을 것이다.

도전

Forte LET표현식 의 단순화 된 서브 세트에 대한 인터프리터를 작성해야합니다 .

이 문법에 따라 일련의 줄을 입력으로 받게됩니다.

<line>::= <number>=<expression>

<expression>::= <number>|<expression>+<number>

참고 :이 문법은 줄 번호, LET 및 괄호 (항상 필수)가 없기 때문에 유효한 Forte가 아닙니다.

즉, 계산 계산 및 숫자에 값 할당 만 처리하면됩니다. 입력에 괄호가 없으며 각 표현식은 왼쪽에서 오른쪽으로 평가해야합니다. 부분 결과는 재정의의 영향을받습니다.

숫자는 항상 음수가 아닌 정수이며 언어의 기본 정수 유형의 한도 (또는 2 ^ 32 중 높은 값)입니다.

각 줄에 대해 표현식의 결과를 출력하고이 결과를 첫 번째 숫자의 (재 할당 된) 값에 할당해야합니다. 이는 다음 줄의 해석 방법에 영향을줍니다.

이것은 가장 짧은 코드 (바이트)가이기는 !

다른 규칙

  • 입력 형식은 유연합니다. 예를 들어 줄 바꿈, 문자열 목록, 숫자 목록이있는 단일 문자열을 사용할 수 있습니다. 입력.
  • 함수, 전체 프로그램 또는 REPL 환경에서 실행할 솔루션을 제출하여 각 라인마다 한 번씩 호출 할 수 있습니다.
  • 표준 허점 은 금지되어 있습니다. 특히 코드에서 외부 Forte 인터프리터를 호출 할 수 없습니다.

이들은 모두 같은 입력의 일부입니다. 각 라인 뒤에 해당 라인에 대한 예상 출력이 표시되며, 때로는 관련 재 할당 (필요한 출력의 일부가 아님)을 나타내는 주석과 함께 표시됩니다.

5=4
4
6=5
4        # 5 -> 4
7=1+2+5
7
7=5+2+1
4        # Order of operations matters! 5+2 -> 4+2 -> 6 -> 4
18=5+6+7
12
5=3
3        # Remember: 5 -> 4
10=6+4
3        # 6 -> 4 -> 3, 3+3 = 6 -> 3

0유효한 숫자는?
orlp

@orlp 0는 유효합니다 ( "숫자는 항상 음수가 아닌 정수입니다")
Leo

산술 연산자를 받아 들여야합니까?
bacchusbeale

@bacchusbeale 아니요, 요약입니다.
Leo

특정 최대 값이 있습니까? 아니면 언어의 기본 정수 유형만큼 큰가요? 또한 숫자 목록을 반환하는 것은 잘못된 출력입니다. 그 중 하나가 결과입니다. (예 : 숫자가 어떤 숫자로가는 사전 /지도 인쇄)
zgrep

답변:


4

젤리 , 28 바이트

®y$ÐL
ṪÇ+Ç¥/Ṅ;®⁸Ǥ;©
⁸©ḷƓÇ€¤

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

이것은 표준 입력에서 입력을받는 것이 더 좋지 않은 몇 가지 Jelly 프로그램 중 하나입니다. 그것은 완전한 프로그램입니다 (함수를 쓰는 것은 짧았지만 두 번째로 올바르게 실행되지 않기 때문에 PPCG 규칙에 의해 금지되었습니다). 입력 형식은 다음과 같습니다.

[[5,[4]],[6,[5]],[7,[1,2,5]],[7,[5,2,1]],[18,[5,6,7]],[5,[3]],[10,[6,4]]]

설명

도우미 함수 1Ŀ (정수를 값으로 변환)

®y$ÐL
   ÐL   Repeatedly, until there are no further changes,
  $       apply the following unary function to {the input}:
 y          replace values using the mapping table
®             stored in the register.
        {Then return the eventual result.}

오히려이 도우미 함수 y는 정의 된 방식으로 인해 단일 값 또는 값 목록에서 올바르게 작동합니다 . 단일 값에 대해 둘 이상의 매핑이 제공되면 테이블에서 첫 번째 매핑을 가져옵니다. 매핑 테이블은 레지스터에 저장됩니다 (기본적으로 변수 일 뿐이며 Jelly에는 하나의 변수 만 있음).

도우미 기능 2Ŀ (하나의 LET 명령어 평가)

ṪÇ+Ç¥/Ṅ;®⁸Ǥ;©
Ṫ               On the last element of {the input},
 Ç              Run 1Ŀ,
     /          left fold it via
    ¥             the following binary function:
  +                 add {the two arguments}
   Ç                and run 1Ŀ on {the result},
      Ṅ         write {the result} (and a newline) to standard output,
       ;®       append the value of the register,
            ;   prepend
           ¤      the following value:
         ⁸          {the input, without its last element}
          Ç         with 1Ŀ run on it
             ©  and store that value in the register {and return it}.

여기서는 실제로 반환 값을 원하지 않습니다. 우리는 부작용을 위해 이것을 실행하고 있습니다 (레지스터를 업데이트하고 할당 된 값을 출력합니다). 젤리 함수는 항상 값을 반환하므로 매핑 테이블이 반환되도록하십시오.

주요 프로그램

⁸©ḷƓÇ€¤
 ©       Initialize the mapping table
⁸        with the empty string (which is also the empty list)
  ḷ      then evaluate and discard
      ¤  the following value:
   Ɠ       a line from standard input, parsed into a data structure
    Ç€     with each element transformed via 2Ŀ
         {and leave the empty string to be printed implicitly}

일반적 으로이 컨텍스트에서 실행될 때 첫 번째 명령 줄 인수를 제공하지만 표준 입력에서 입력을받지 않으므로 null 문자열을 제공하는 대체 모드에서 실행됩니다. 레지스터를 초기화 할 필요가 있습니다 (기본값에서 0충돌이 발생 함 y)는 사용자의 입력을 암시 적으로 언급 할 수 없다는 것을 의미합니다. 즉 표준 입력 ( Ɠ) 에서 가져 오는 것보다 값이 저렴합니다 . 명령 줄 인수 ( ³또는 )를 사용하고 대체 사용에 액세스 할 수 있다는 것은 비정상적인 (Jelly의 경우) 입력 형식이 실제로 바이트보다 짧다는 것을 의미합니다.

이것이 불가능할 수도 있습니다. 나는 여전히 두 번째 줄 ⁸Ǥ;이 단지 왜 라기보다는 말해야 하는지를 알지 못했다. / / ;@Ç의 사용이 부족하다는 점에서 젤리를 이해 하는 한 두 줄 이 동일해야 하지만 후자는 어떤 이유로 충돌한다. 마찬가지로 바이트를 잃지 않고 프로그램을 다시 정렬하는 다른 방법이 있으므로 조금 더 짧게 만드는 방법을 놓쳤을 수 있습니다.µðø

또한, 마지막 행에서를 변경하면 ;프로그램의 내부 작업에 대한 흥미로운 모습 을 얻을 수 있습니다.이 함수는의 반환 값에 의해 암시 적으로 출력되는 "레지스터의 기록"을 출력합니다 2Ḷ.


5

펄 5 , 92 바이트

90 바이트의 코드 + -pl플래그

sub f{($b=$h{$a=pop}//$a)!=$a?f($b):$a}s%(\d+)\+(\d+)%f($1)+f$2%e&&redo;/=/;$_=$h{f$`}=f$'

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

해시 테이블 %h을 사용하여 숫자 간의 매핑을 저장합니다.
함수 ( sub) f는 입력 맵이있는 숫자 (또는 숫자가없는 경우 입력 )를 반환합니다 $h{$a=pop}. 입력이 맵핑되는 숫자를 검색합니다. 이 값이 없으면 //$a의 값은 ($b=$h{$a=pop}//$a)입력 값 ( $a)입니다. 우리는이 값이 무한히 반복되지 않는 입력 자체가 아닌지 확인합니다 ( !=$a). 그런 다음 재귀 적으로 f입력을 호출 하거나 반환합니다.
기본 프로그램은 두 단계로 구성됩니다
.- s%(\d+)\+(\d+)%f($1)+f$2%e&&redo오른쪽에있는 첫 번째 추가를 평가하지만 여전히 추가가 있습니다 . x+y이 평가 결과는로 평가 f(x)+f(y)됩니다.
- /=/;$_=$h{f$`}=f$'과제를 수행합니다./=/을 사용하여 왼쪽에 액세스하고을 사용 $`하여 오른쪽 에 액세스 $'한 다음 $h{f$`}=f$'할당을 수행합니다. 또한 $_각 줄 다음에 암시 적으로 인쇄 되는 것을 할당합니다 .


5

자바 스크립트 (Node.js) , 81 바이트

v=x=>(v[x]=v[x]||x,v[x]-x?v(v[x]):x)
f=x=>l=>v[v(x)]=l.reduce((p,x)=>v(v(x)+p),0)

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

할당 할 값으로 f를 호출 한 다음 그 결과를 함께 추가 할 값 배열로 호출하여 입력을받습니다. (즉, f(5)([4])여러 라인)를 반복합니다.

v숫자의 실제 현재 값을 계산하는 함수로 사용되며 실제 값을 저장하는 객체로도 사용됩니다. 먼저 정의되어 v[x]=v[x]||x있는지 확인하십시오 v[x]. v[x]-x이것이 실제 숫자인지 아닌지를 판별하기 위해 비교를 수행합니다. 숫자가 자신에게 매핑되지 않으면 v(v[x])재귀 적으로 다시 시도하고 그렇지 않으면을 반환 x합니다.

f 1 바이트를 저장하도록 카레 된 계산 및 할당을 수행하며, 두 번째 호출은 계산 된 값을 반환합니다.


3

하스켈 , 116 113 108 106 바이트

(#)=until=<<((==)=<<)
e?((n,s):r)|m<-foldl1(\a b->e#(e#a+e#b))s=m:(\x->last$m:[e#x|x/=e#n])?r
e?r=[]
(id?)

온라인으로 사용해보십시오! 각 방정식은 4=3+1+5튜플로 표기된다 (4,[3,1,5]). 익명 함수 (id?)는 이러한 튜플 목록을 가져와 모든 중간 결과 목록을 반환합니다.

#주어진 함수 e의 시작점과 시작 값 을 찾는 함수 x입니다.

이 함수 ?는 평가 함수 e를 사용하여 각 방정식을 재귀 적으로 해결합니다. foldl1(\a b->e#(e#a+e#b))s수학 식의 우변을 계산하고 그 결과를 저장 m을 위해, 예를 4=3+1+5그것이 계산 eval(eval(eval 3 + eval 1) + eval 5)각각은 여기서 eval의 고정 점 애플리케이션이다 e. 그런 다음 평가 기능의 새로운 과제 수행하도록 수정 n: 계정에 (\x->last$m:[e#x|x/=e#n])동일하다 \x -> if x == eval n then m else eval x.

초기 평가 함수는 id각 정수를 자체에 매핑하는 것입니다.


더 짧은 수정 점 기능을위한 Ørjan Johansen 덕분에 2 바이트를 절약 할 수 있습니다!


좋은 작업! 그건 그렇고 당신은 모든 중간 결과를 반환해야합니다, 그래서 당신은 떨어질 수 있습니다last.
Leo

2
(#)e=until((==)=<<e)e또는 (#)=until=<<((==)=<<)더 짧습니다.
Ørjan Johansen

@ ØrjanJohansen 감사합니다!
Laikoni

3

oK, 48 바이트

a:[];s:{*(a@x;x)^0N}/;f:{a[s@x]:y:{s@x+y}/s'y;y}

용법: f[5;1 2 3] / 5=1+2+3

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


0through 만 사용하는 것과 같이 사용할 수있는 수의 상한을 신경 쓰지 않으면 998다음과 같이 충분합니다 ( 최대 값에 따라 41 바이트 ± 몇 개).

a:!999;s:(a@)/;f:{a[s@x]:y:{s@x+y}/s'y;y}

설명:

; 세 가지 정의를 구분합니다.

a사전 / 숫자 맵입니다. 첫 번째 경우, 그것은 실제, 빈 사전의 []두 번째 경우에는 번호 목록입니다, 0에가 998.

s숫자가 주어지면 "결과"숫자를 찾는 함수입니다. /출력이 멈출 때까지 변경이 자체 출력 자체를 적용하는 기능 수단의 끝에.

마지막 비트는 다음 f을 의미합니다.

f:{                      } /function called f, input number x, list y
                    s'y    /apply s to every number in the list
                   /       /fold through the list
            {s@x+y}        /    sum the two numbers, apply s
   a[s@x]:                 /set the s(x) to map to the final sum
          y:           ;y  /redefine y to be the final sum, then return it

3

파이썬 3 146 132 130 바이트

@Dada 덕분에 14 바이트 절약
@ mbomb007 덕분에 2 바이트 절약

d={}
g=lambda x:d.get(x)and x!=d[x]and g(d[x])or x
def f(t):
 for n,(s,*r)in t:
  for b in r:s=g(g(s)+g(b))
  d[g(n)]=s;yield g(n)

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

입력을 방정식의 튜플 [ x = y + z + was (x, (y, z, w))] 로 받고 생성기를 통해 출력합니다.


테스트 할 수 있도록 호출 예제를 보여줄 수 있습니까?
Leo

1
@Leo 님이 TIO를 추가했습니다.
Uriel

1
g아마 쓸 수있었습니다 g=lambda x:d.get(x)and d[x]!=x and g(d[x])or x. 그리고 2 대신 들여 쓰기 위해 1 개의 공백을 사용할 수 있다고 생각합니다. [132 바이트]로 이동하십시오 ( 온라인 시도하십시오! ).
Dada

1
감사합니다! 너무
Uriel

1
반 공백 들여 쓰기는 없지만 두 가지 공백 대신 단일 탭을 사용하는 또 다른 깔끔한 요령이 있습니다. 들여 쓰기가 다른 한, 파이썬은 행복합니다 (예를 들어, 추가 중첩 레벨의 들여 쓰기로 스페이스 탭과 탭 스페이스를 사용할 수 있습니다). 이것은 두 바이트를 절약 할 수 있습니다 :)
Leo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.