Tổng kết? Đó là sở trường của tôi!


18

Giới thiệu

Forte là một ngôn ngữ bí truyền rất đặc biệt dựa trên khái niệm sửa đổi các giá trị của các con số. Trong số Forte không phải là hằng số mà là biến, bạn có thể sử dụng LEThướng dẫn để gán giá trị mới cho chúng.

Ví dụ, sau khi thực hiện LET 2=4-1từ bây giờ, 2giả sử giá trị của 3, điều đó có nghĩa là bất cứ khi nào giá trị 2xuất hiện trong một biểu thức, nó sẽ được "thay thế" bằng 3. Các biểu thức (1+1)*2bây giờ sẽ đánh giá để 9.

Hướng dẫn này trong Forte được sử dụng cả để lưu trữ thông tin và kiểm soát luồng (các dòng được đánh số và bằng cách thay đổi giá trị số của chúng, bạn có thể xác định thứ tự thực hiện của chúng). Trong thử thách này, chúng tôi sẽ không đối phó với khía cạnh thứ hai này.

Các thách thức

Bạn được yêu cầu viết một trình thông dịch cho một tập hợp con đơn giản của các LETbiểu thức của Forte .

Bạn sẽ nhận được như là một loạt các dòng theo ngữ pháp này:

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

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

Lưu ý: ngữ pháp này không hợp lệ Forte vì nó thiếu số dòng, LET và dấu ngoặc đơn (luôn luôn bắt buộc)

Đó là, bạn sẽ chỉ cần xử lý các phép tính tổng và gán giá trị cho các số. Dấu ngoặc đơn sẽ không xuất hiện trong đầu vào và mỗi biểu thức sẽ cần được đánh giá từ trái sang phải: coi chừng kết quả một phần bị ảnh hưởng bởi các định nghĩa lại!

Các số sẽ luôn là số nguyên không âm, tối đa giới hạn của kiểu số nguyên gốc của ngôn ngữ của bạn (hoặc 2 ^ 32, tùy theo giá trị nào cao hơn).

Đối với mỗi dòng, bạn nên xuất kết quả của biểu thức và gán kết quả này cho giá trị (có thể được gán lại) của số đầu tiên, điều này sẽ ảnh hưởng đến cách các dòng sau sẽ được diễn giải.

Đây là , mã ngắn nhất (tính bằng byte) sẽ thắng!

Các quy tắc khác

  • Định dạng đầu vào rất linh hoạt, ví dụ bạn có thể lấy một chuỗi có dòng mới, danh sách các chuỗi, danh sách các số ... Tương tự với đầu ra, miễn là kết quả của từng biểu thức trong đó là gì đầu vào.
  • Bạn có thể gửi một chức năng, một chương trình đầy đủ hoặc một giải pháp để được chạy trong môi trường REPL gọi nó một lần cho mỗi dòng.
  • Các lỗ hổng tiêu chuẩn bị cấm, đặc biệt bạn không thể gọi một trình thông dịch Forte bên ngoài trong mã của mình.

Ví dụ

Đây là tất cả các phần của cùng một đầu vào. Sau mỗi dòng, đầu ra dự kiến ​​liên quan đến dòng đó được hiển thị, đôi khi với một nhận xét cho biết việc gán lại có liên quan (không phải là một phần của đầu ra cần thiết).

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

0một số hợp lệ?
orlp

@orlp 0là hợp lệ ("Số sẽ luôn là số nguyên không âm")
Leo

Chúng ta có nên chấp nhận bất kỳ toán tử số học?
bacchusbeale

@bacchusbeale Không, chỉ là tổng kết.
Leo

Có số lượng tối đa cụ thể nào không, hay nó có lớn như kiểu số nguyên của ngôn ngữ không? Ngoài ra, nó sẽ là đầu ra không hợp lệ để trả về một danh sách các số, một trong số đó là kết quả, phải không? (chẳng hạn như in từ điển / bản đồ cho số nào đi đến số nào)
zgrep

Câu trả lời:


4

Thạch , 28 byte

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

Hãy thử trực tuyến!

Đây là một trong số ít các chương trình Jelly mà dường như có xu hướng lấy đầu vào từ đầu vào tiêu chuẩn. Đó là một chương trình đầy đủ (viết một chức năng sẽ ngắn hơn nhưng bị cấm bởi các quy tắc PPCG, vì nó sẽ không chạy đúng lần thứ hai). Định dạng đầu vào trông như thế này:

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

Giải trình

Hàm trợ giúp 1Ŀ (dịch một số nguyên thành giá trị của nó)

®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.}

Khá thuận tiện, hàm trợ giúp này sẽ hoạt động chính xác trên một giá trị hoặc danh sách các giá trị, do cách yđược xác định. Nếu có nhiều hơn một ánh xạ được đưa ra cho một giá trị, chúng ta sẽ lấy ánh xạ đầu tiên từ bảng. Bảng ánh xạ được lưu trữ trong thanh ghi (về cơ bản chỉ là một biến; Jelly chỉ có một biến).

Hàm trợ giúp 2Ŀ (đánh giá một lệnh 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}.

Chúng tôi không thực sự muốn một giá trị trả lại ở đây; chúng tôi chỉ chạy cái này cho các tác dụng phụ của nó (cập nhật thanh ghi và xuất giá trị được gán). Mặc dù vậy, các hàm Jelly luôn trả về một giá trị, vì vậy chúng ta chỉ để bảng ánh xạ được trả về, vì đó là mức thấp nhất.

Chương trình chính

⁸©ḷƓÇ€¤
 ©       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}

Thông thường, sẽ cung cấp cho chúng ta đối số dòng lệnh đầu tiên khi chạy trong ngữ cảnh này, nhưng không có đối số (chúng ta đang lấy đầu vào từ đầu vào tiêu chuẩn), do đó, nó chạy trong chế độ thay thế cung cấp cho chúng ta chuỗi null. Nhu cầu khởi tạo thanh ghi (từ giá trị mặc định của 0nó bị sập y) có nghĩa là chúng tôi không thể đề cập đến đầu vào của người dùng một cách ngầm định, có nghĩa là nó rẻ khi lấy nó từ đầu vào tiêu chuẩn ( Ɠ) vì nó sẽ lấy nó từ một đối số dòng lệnh ( ³hoặc ) và có thể truy cập vào cách sử dụng thay thế có nghĩa là dạng đầu vào bất thường (đối với Jelly) thực sự ngắn hơn một byte.

Có thể đây là điều ngẫu hứng. Tôi vẫn chưa tìm ra lý do tại sao dòng thứ hai cần phải nói ⁸Ǥ;thay vì chỉ ;@Ç- hai dòng này phải tương đương, theo như tôi hiểu Jelly, vì thiếu sử dụng µ/ ð/ ø- nhưng vì lý do nào đó bị hỏng. Tương tự, có nhiều cách khác để sắp xếp lại chương trình mà không mất byte, vì vậy có thể tôi đã bỏ lỡ một cách để làm mọi thứ ngắn hơn một chút.

Ngẫu nhiên, việc thay đổi dòng cuối cùng để ;mang đến cho bạn cái nhìn thú vị về hoạt động bên trong của chương trình, vì sau đó nó sẽ xuất ra "lịch sử của thanh ghi" mà xuất ra theo giá trị trả về của nó 2Ḷ.


5

Perl 5 , 92 byte

90 byte mã + -plcờ.

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

Hãy thử trực tuyến!

Tôi sử dụng hashtable %hđể lưu trữ ánh xạ giữa các số.
Hàm ( sub) ftrả về số mà bản đồ đầu vào của nó (hoặc đầu vào của nó nếu nó được ánh xạ thành không có số): $h{$a=pop}lấy số mà ánh xạ đầu vào. Nếu không, nhờ //$a, giá trị của ($b=$h{$a=pop}//$a)là đầu vào ( $a). Chúng tôi đảm bảo rằng các giá trị này không phải là đầu vào để không lặp vô hạn ( !=$a). Sau đó, chúng tôi hoặc gọi đệ quy fhoặc trả lại đầu vào.
Chương trình chính bao gồm hai bước:
- s%(\d+)\+(\d+)%f($1)+f$2%e&&redođánh giá phần bổ sung đầu tiên ở bên phải, trong khi vẫn có phần bổ sung: nó thay thế x+ybằng kết quả đánh giá f(x)+f(y).
- /=/;$_=$h{f$`}=f$'thực hiện nhiệm vụ:/=/cho phép truy cập bên trái với $`và bên phải với $', sau đó $h{f$`}=f$'thực hiện nhiệm vụ. Và chúng tôi cũng gán nó cho nó $_được in ngầm sau mỗi dòng.


5

JavaScript (Node.js) , 81 byte

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)

Hãy thử trực tuyến!

Nhận đầu vào bằng cách gọi f với giá trị cần gán, sau đó gọi kết quả của giá trị đó bằng một mảng các giá trị để cộng lại. (tức là f(5)([4])) Lặp lại cho nhiều dòng.

vđược sử dụng như một hàm để tính giá trị hiện tại thực của một số và cũng là một đối tượng để lưu trữ các giá trị thực tế. Đầu tiên v[x]=v[x]||xđảm bảo rằng v[x]được xác định. v[x]-xthực hiện so sánh để xác định xem đây có phải là con số thực tế hay không. Nếu số không ánh xạ tới chính nó, v(v[x])đệ quy thử lại, nếu không thì trả về x.

f thực hiện tính toán và gán, được xử lý để lưu một byte, trong đó cuộc gọi thứ hai trả về giá trị được tính.


3

Haskell , 116 113 108 106 byte

(#)=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?)

Hãy thử trực tuyến! Mỗi phương trình 4=3+1+5được ký hiệu là tuple (4,[3,1,5]). Hàm ẩn danh (id?)nhận một danh sách các bộ dữ liệu như vậy và trả về một danh sách tất cả các kết quả trung gian.

#là một hàm để tìm điểm cố định của hàm đã cho evà giá trị bắt đầu x.

Hàm ?lấy một hàm đánh giá evà giải đệ quy từng phương trình. foldl1(\a b->e#(e#a+e#b))sđánh giá phía bên phải của một phương trình và lưu kết quả vào m, ví dụ cho 4=3+1+5nó tính toán eval(eval(eval 3 + eval 1) + eval 5), trong đó mỗi phương thức evallà một ứng dụng điểm cố định e. Sau đó, hàm eval được sửa đổi để thực hiện chuyển nhượng mới nvào tài khoản: (\x->last$m:[e#x|x/=e#n])tương tự như \x -> if x == eval n then m else eval x.

Hàm đánh giá ban đầu là idánh xạ từng số nguyên cho chính nó.


Cảm ơn Ørjan Johansen cho chức năng sửa lỗi ngắn hơn, tiết kiệm 2 byte!


Công việc tốt! Bằng cách này, bạn được yêu cầu trả lại tất cả các kết quả trung gian, vì vậy bạn có thể bỏ qualast.
Leo

2
(#)e=until((==)=<<e)ehoặc (#)=until=<<((==)=<<)ngắn hơn.
Ørjan Johansen

@ RjanJohansen Cảm ơn rất nhiều!
Laikoni

3

oK, 48 byte

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

Sử dụng: f[5;1 2 3] / 5=1+2+3

Hãy thử trực tuyến!


Nếu bạn không có giới hạn trên đối với các số bạn có thể sử dụng, chẳng hạn như chỉ sử dụng các số 0thông qua 998, thì các điều kiện sau ( 41 byte ± một vài tùy thuộc vào mức tối đa):

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

Giải trình:

; tách ba định nghĩa.

alà một từ điển / bản đồ số. Trong trường hợp đầu tiên, nó là một thực tế, từ điển rỗng [], trong trường hợp thứ hai đó là một danh sách các số điện thoại 0để 998.

slà một hàm tìm số "kết quả" khi được cung cấp một số. Phần /cuối của hàm có nghĩa là nó sẽ tự áp dụng cho đầu ra của chính nó cho đến khi đầu ra dừng thay đổi.

Bit cuối cùng f, có nghĩa là:

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

Python 3, 146 132 130 byte

14 byte được lưu nhờ @Dada
2 byte được lưu nhờ @ mbomb007

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)

Hãy thử trực tuyến!

Nhận đầu vào dưới dạng bộ phương trình [ x = y + z + was (x, (y, z, w))], đầu ra thông qua trình tạo.


Bạn có thể hiển thị một ví dụ gọi để nó có thể được kiểm tra?
Leo

1
@Leo thêm TIO.
Uriel

1
gcó lẽ có thể được viết g=lambda x:d.get(x)and d[x]!=x and g(d[x])or x. Và tôi nghĩ rằng bạn có thể sử dụng 1 khoảng trắng để thụt lề thay vì 2. Điều đó sẽ đưa bạn đến [132 byte] ( Hãy thử trực tuyến! ).
Dada

1
@Dada cảm ơn! quá tệ, họ không có thụt lề nửa không gian: P
Uriel

1
Không có thụt lề nửa không gian, nhưng một mẹo gọn gàng khác là sử dụng một tab duy nhất thay vì hai khoảng trắng. Miễn là các vết lõm khác nhau, Python rất vui (ví dụ bạn có thể sử dụng tab không gian và không gian tab làm vết lõm ở các mức lồng nhau bổ sung). Điều này có thể giúp bạn tiết kiệm hai byte :)
Leo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.