ข้อสรุป? นั่นคือมือขวาของฉัน!


18

บทนำ

Forteเป็นภาษาลึกลับที่แปลกประหลาดมากขึ้นอยู่กับแนวคิดของการปรับเปลี่ยนค่าของตัวเลข ในหมายเลข Forte ไม่ใช่ค่าคงที่ แต่เป็นตัวแปรคุณสามารถใช้LETคำสั่งเพื่อกำหนดค่าใหม่ให้กับพวกเขา

ตัวอย่างเช่นหลังจากการดำเนินการLET 2=4-1ต่อจากนี้ไป2จะถือว่าค่าของ3ซึ่งหมายความว่าเมื่อใดก็ตามที่มีค่า2ขึ้นมาในการแสดงออกของมันคือแทนที่จะเป็น "แทนที่" 3โดย การแสดงออกในขณะนี้จะประเมิน(1+1)*29

คำแนะนำใน Forte นี้ใช้สำหรับการจัดเก็บข้อมูลและควบคุมการไหล (มีการกำหนดหมายเลขบรรทัดและโดยการเปลี่ยนค่าของตัวเลขคุณสามารถกำหนดลำดับของการดำเนินการได้) ในการท้าทายนี้เราจะไม่จัดการกับประเด็นที่สองนี้

ความท้าทาย

คุณจะต้องเขียนล่ามสำหรับชุดย่อยที่เรียบง่ายของการLETแสดงออกของ Forte

คุณจะได้รับชุดข้อมูลของบรรทัดตามไวยากรณ์นี้:

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

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

หมายเหตุ: ไวยากรณ์นี้ไม่ถูกต้อง Forte เนื่องจากไม่มีหมายเลขบรรทัด LET และวงเล็บ (ซึ่งจำเป็นต้องมีเสมอ)

นั่นคือคุณจะต้องจัดการกับการสรุปผลการคำนวณและการกำหนดค่าให้กับตัวเลขเท่านั้น เครื่องหมายวงเล็บจะไม่ปรากฏในอินพุตและแต่ละนิพจน์จะต้องได้รับการประเมินจากซ้ายไปขวา: ระวังว่าผลลัพธ์บางส่วนได้รับผลกระทบจากการกำหนดใหม่!

ตัวเลขจะเป็นจำนวนเต็มแบบไม่ลบเสมอจนถึงขีด จำกัด ของจำนวนเต็มพื้นฐานของภาษาของคุณ (หรือ 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
ṪÇ+Ç¥/Ṅ;®⁸Ǥ;©
⁸©ḷƓÇ€¤

ลองออนไลน์!

นี่เป็นหนึ่งในไม่กี่โปรแกรมของเยลลี่ที่ดูเหมือนว่าจะพยายามเอาข้อมูลจากอินพุตมาตรฐาน มันเป็นโปรแกรมเต็มรูปแบบ (การเขียนฟังก์ชั่นจะสั้นลง แต่ถูกห้ามโดยกฎ 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กำหนดไว้ หากมีการมอบการแมปมากกว่าหนึ่งรายการสำหรับค่าเดียวเราจะทำการจับคู่ครั้งแรกจากตาราง ตารางการแมปจะถูกเก็บไว้ในรีจิสเตอร์ (ซึ่งโดยทั่วไปเป็นเพียงตัวแปร; เจลลี่มีเพียงหนึ่งตัวแปร)

ฟังก์ชั่นตัวช่วย 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

Perl 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$'

ลองออนไลน์!

ฉันใช้ hashtable %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

JavaScript (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 ทำการคำนวณและการมอบหมาย curried เพื่อบันทึกหนึ่งไบต์ที่โทรที่สองส่งกลับค่าที่คำนวณ


3

Haskell , 116 113 108 106 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เป็น notated เป็น (4,[3,1,5])tuple ฟังก์ชั่นที่ไม่ระบุชื่อ(id?)ใช้รายการของสิ่งอันดับและส่งกลับรายการผลลัพธ์กลางทั้งหมด

#เป็นฟังก์ชั่นเพื่อหา fixpoint ของฟังก์ชั่นที่กำหนดและความคุ้มค่าเริ่มต้นex

ฟังก์ชัน?ใช้ฟังก์ชันการประเมินผล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จากนั้นฟังก์ชั่น EVAL มีการแก้ไขที่จะใช้งานใหม่ของnเข้าบัญชี: ซึ่งเป็นเช่นเดียวกับ(\x->last$m:[e#x|x/=e#n])\x -> if x == eval n then m else eval x

ฟังก์ชั่นเริ่มต้นการประเมินผลidซึ่งแผนที่แต่ละจำนวนเต็มกับตัวเอง


ขอบคุณØrjan Johansen สำหรับฟังก์ชั่น fixpoint ที่สั้นกว่าประหยัด 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

ลองออนไลน์!


หากคุณไม่ทราบมีขีด จำกัด บนไปยังหมายเลขที่คุณสามารถใช้เช่นใช้เพียงตัวเลข0ผ่าน998แล้วพอเพียงต่อไปนี้ ( 41 ไบต์ ±ไม่กี่ขึ้นอยู่กับสูงสุด):

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

คำอธิบาย:

; แยกสามคำจำกัดความ

aเป็นพจนานุกรม / แผนที่ของตัวเลข ในกรณีแรกก็เป็นจริง, พจนานุกรมที่ว่างเปล่า[]ในกรณีที่สองมันเป็นรายการของตัวเลขที่จะ0998

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

Python 3, 146 132 130 ไบต์

บันทึก 14 ไบต์ขอบคุณ @Dada
บันทึก 2 ไบต์ขอบคุณ @ 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)

ลองออนไลน์!

รับอินพุตเป็น tuples ของสมการ [ x = y + z + was (x, (y, z, w))] เอาต์พุตผ่านตัวสร้าง


คุณสามารถแสดงตัวอย่างการเรียกใช้เพื่อให้สามารถทดสอบได้หรือไม่
Leo

1
@Leo เพิ่ม TIO
Uriel

1
gg=lambda x:d.get(x)and d[x]!=x and g(d[x])or xอาจจะเขียนได้ และฉันคิดว่าคุณสามารถใช้ 1 ช่องว่างเพื่อเยื้องแทน 2 ได้คุณควรไปที่ [132 bytes] ( ลองออนไลน์! )
Dada

1
@Dada ขอบคุณ! เลวร้ายเกินไปที่พวกเขาไม่มีการเยื้องครึ่งช่อง: P
Uriel

1
ไม่มีการเยื้องครึ่งช่องว่าง แต่เคล็ดลับเรียบร้อยก็คือการใช้แท็บเดียวแทนที่จะเป็นสองช่องว่าง ตราบใดที่การเยื้องแตกต่างกัน Python ก็ยินดี (ตัวอย่างเช่นคุณสามารถใช้ space-tab และ tab-space เป็นการเยื้องระดับที่ซ้อนกันเพิ่มเติม) นี้สามารถช่วยให้คุณประหยัดไบต์ที่สอง :)
สิงห์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.