การคูณด้วยการดัดแปลงตัวเอง


33

... อย่างน้อยสำหรับคำจำกัดความของ "การดัดแปลงตนเอง"

งาน

ในความท้าทายนี้งานของคุณคือการเขียนสามสายA, BและCที่ตอบสนองคุณสมบัติดังต่อไปนี้

  • สตริงBมีความยาวอย่างน้อย 1

  • สำหรับทุก ๆn ≥ 0สตริงเป็นโปรแกรมที่ถูกต้อง (หมายถึงโปรแกรมที่รันได้เต็มหรือนิยามฟังก์ชัน) ในภาษาการเขียนโปรแกรมที่คุณเลือก ยกหมายถึงการทำซ้ำเพื่อให้ที่นี้หมายถึงสตริง, , , ฯลฯ แต่ละโปรแกรมจะใช้เวลาหนึ่งสตริงเป็น input และผลตอบแทนที่หนึ่งสายเป็นผลผลิตABnCACABCABBCABBBC

  • สำหรับการใด ๆm, n ≥ 0ถ้าโปรแกรมจะดำเนินการด้วยการป้อนข้อมูลก็จะส่งกลับ สำหรับอินพุตที่ไม่ใช่แบบฟอร์มนี้โปรแกรมอาจทำสิ่งใดก็ได้รวมถึงข้อขัดข้องABmCABnCABm*n+1C

ตัวอย่างบางส่วนในรูปแบบprogram(input) -> output:

AC(AC) -> ABC
ABC(AC) -> ABC
ABBBBBC(AC) -> ABC
AC(ABC) -> ABC
AC(ABBBBC) -> ABC
ABC(ABC) -> ABBC
ABBC(ABC) -> ABBBC
ABBBBC(ABBBC) -> ABBBBBBBBBBBBBC
ABBBC(ABBBBBBC) -> ABBBBBBBBBBBBBBBBBBBC

กฎและเกณฑ์การให้คะแนน

คะแนนของคุณคือความยาวรวมAและCคะแนนที่ต่ำกว่าดีกว่า โปรดทราบว่าในขณะที่Bไม่ได้นับรวมคะแนนจะต้องสร้างโดยAและCในตัวอย่างแรก

ช่องโหว่มาตรฐานไม่ได้รับอนุญาต โปรแกรมไม่ได้รับอนุญาตให้เข้าถึงซอร์สโค้ดของตนเองโดยตรงหรือโดยอ้อม (ยกเว้นเมื่อได้รับเป็นอินพุต) คุณจะต้องระบุสตริงA, BและCในคำตอบของคุณในบางวิธีและเป็นกำลังใจที่จะอธิบายถึงวิธีการแก้ปัญหาของคุณ

คำตอบ:


16

CJam, 9 8 ไบต์

A: 1
B: 0
C:  r,(#0q

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

(ABcode) e# Push the integer 10 ** len(Bcode).
<SP>     e# Noop. Separates (AB) and C for input reading.
r        e# Read the first whitespace-separated token from STDIN (ABinput).
,(       e# Push the string length minus 1: len(Binput)
#        e# Power operator: 10 ** len(Bcode) len(Binput) # ->
         e#   (10 ** len(Bcode)) ** len(Binput) = 10 ** (len(Bcode) * len(Binput))
0        e# Push an additional 0 to complete len(Bcode) * len(Binput) + 1 zeroes.
q        e# Read the remaining input (C).

12

CJam, 15 13 11 ไบต์

A: rl"
B: <SP>
C: <LF>",(*SNq

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

e# A

r     e# Read a whitespace-separated token from STDIN.
      e# This reads the input up to the first space, but does not consume it.
l     e# Read the rest of the first line from STDIN.
      e# This reads up to the first linefeed and consumes it.

"     e# Initiate a string.

e# B

<SP>  e# Fill the string with as many spaces as there are copies of B.

e# C

<LF>" e# Terminate the string with a linefeed.
      e# This serves as a delimiter for the `l' command.
,(    e# Compute the length of the string minus 1 (to account for the LF).
*     e# Repeat the string read by `l' that many times.
SN    e# Push a space and a linefeed.
q     e# Read the remaining input (i.e., the second line) from STDIN.

ในตอนท้ายสแต็คที่มีการอ่านโทเค็นโดยrพื้นที่ที่ผลิตโดย*พื้นที่และผลักดันโดยเลื่อนบรรทัดและบรรทัดอ่านโดยSN qCJam พิมพ์สิ่งเหล่านี้โดยอัตโนมัติ


ฮะใช้ประโยชน์จากคำพูดที่นั่น: D
เครื่องมือเพิ่มประสิทธิภาพ

9

Pyth, 10

A: w*\0hl*w[<newline>
B: 0
C: <empty>

เราแบ่งแหล่งที่มาเป็นสองบรรทัด บรรทัดแรกคือ A บรรทัดที่สองคือ Bs เนื่องจาก A อยู่ในบรรทัดแรกดังนั้นwเพียงแค่พิมพ์ A - ง่ายเสร็จแล้ว

ใน Pyth zeroes ชั้นนำราชสกุลแยกเพื่อให้เป็นจริง[00) [0, 0]โปรดทราบว่าครั้งแรกที่ปลายสายและสายที่สองประกอบด้วยl[ 0000...ดังนั้นจึงl[นับจำนวน Bs ในโปรแกรมนี้ ครั้งที่สองwอ่านในบรรทัดที่สองของอินพุต - นี่คือจำนวน Bs ของอินพุต จากที่นี่มันเป็นการคูณการเพิ่มและเอาท์พุทแบบง่ายๆ


9

เรติน่า25 25ไบต์

A: ]\]<LF>
B: ]]
C: <LF>m`^]*$<LF>]$0]

<LF> stands for newline

ABCรหัสตัวอย่าง:

]\]
]]
m`^]*$
]$0]

รหัสมีสองขั้นตอนการทดแทน:

  • เปลี่ยนอินพุตAB^mCเป็นAB^(m*n)Cโดยเปลี่ยนทุกอย่างBเป็นB^n:

    • ]\]จับคู่ทุกอย่างBในอินพุตและไม่มีอะไรอื่นขอบคุณที่หลบหนีไปในเส้นรูปแบบ
    • ]]...]] คือ B^n
  • เปลี่ยนB^(m*n)เป็นB^(m*n+1)โดย

    • m`^]*$รับสายที่มีเพียง]ของ
    • ]$0]เพิ่มคู่พิเศษของ]]มันในลักษณะที่บรรทัดนี้ไม่ตรงกับ regex แรก

ฉันได้เพิ่ม 3 ไบต์ไปยังคะแนนสำหรับการตั้งค่า-sหลายบรรทัดซึ่งจำเป็นเพื่อให้รหัส Retina ทั้งหมดอาจเป็นไฟล์เดียว

บันทึก 2 ไบต์ด้วย @ MartinBüttner


8

Python 3, 51 ไบต์

A: lambda s:s[:28]+"x"*(1+len("
B: x
C: ")*(len(s)-51))+s[-23:]

ตัวอย่างการใช้งาน:

>>> f=lambda s:s[:28]+"x"*(1+len("xx")*(len(s)-51))+s[-23:]
>>> f('lambda s:s[:28]+"x"*(1+len("xxx")*(len(s)-51))+s[-23:]')
'lambda s:s[:28]+"x"*(1+len("xxxxxxx")*(len(s)-51))+s[-23:]'

ฟังก์ชั่นคำนวณn*m+1โดย(1+len("xxx")*(len(s)-51))ที่มีอยู่m xในสตริง ( xxxส่วนคือB^m) คูณสตริง"x"ที่มีจำนวนนี้จะช่วยให้B^(n*m+1)และฟังก์ชั่นใช้เวลาAและออกจากการป้อนข้อมูลและเชื่อมทั้งหมดเหล่านี้จะได้รับCAB^(n*m+1)C

วิธีการเดียวกันใน J:

J, 35 ไบต์

A: (19{.]),('x'#~1+(#'
B: x
C: ')*35-~#),_16{.]

5

CJam, 22

A:<empty>
B:{])`\,q,K/(*))*"_~"}
C:{])`\,q,K/(*))*"_~"}_~

ตัวอย่างการเรียกใช้:

ABBC(ABC) -> ABBBC

ซึ่งแปลว่า

{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

ด้วยการป้อนข้อมูลเป็น

{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

ซึ่งให้ผลลัพธ์ต่อไปนี้:

{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

มันทำงานอย่างไร :

ให้ดูที่โปรแกรมACและABCหน้าตา:

AC :{])`\,q,K/(*))*"_~"}_~
ABC:{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

เราสังเกตเห็นว่าC=B_~

ให้ดูสิ่งที่Bกำลังทำ:

{])`\,q,K/(*))*"_~"}

{                  }    e# This is a code block. Alone, this does nothing except
                        e# pushing this block to stack as is
 ]                      e# Wrap everything on stack in an array
  )`                    e# Take out the last part and convert it to its string representation
    \,                  e# Take length of remaining array
      q,K/              e# Read the input, take its length and int divide by K (i.e. 20)
          (*            e# Decrement and multiply by the array length on stack
            ))          e# Add two to the product
              *         e# Repeat the string representation on stack that many times
               "_~"     e# Put this string on stack

ตอนนี้ให้ดูสิ่งที่ทำงานACโดยไม่ต้องป้อนข้อมูลใด ๆ จะทำ:

{])`\,q,K/(*))*"_~"}_~                      e# Copy the block and run it
{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}~   e# Block is copied, run it
{      ...         } ])                     e# Wrapped array has the block in it.
                       `\,                  e# Stringify it and take length of remaining = 0
                          q,K/              e# No input so 0
                              (*))          e# 0 * -1 = 0. 0 + 2 = 2
                                  *         e# Repeat the stringified block 2 times:
                                            e# "{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}"
                                   "_~"     e# Put this string. Program ends, so print stack:
                                            e# {])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

ABCว้าวออกเป็น

โดยทั่วไปเรานับจำนวนที่Bมีอยู่ในรหัส จากนั้นมีจำนวนเท่าใดในอินพุต (โดยใช้ความยาว) เพิ่มทวีคูณเพิ่มขึ้นสองเท่า (นับจากCนี้B) และต่อท้าย_~เพื่อรับC

ลองออนไลน์ได้ที่นี่


3

Haskell , 50 ไบต์

fStringเป็นฟังก์ชั่นการถ่ายและกลับ

สตริง B เป็นเพียงช่องว่างเดียวในขณะที่ C เริ่มต้นด้วยหนึ่ง

A:_:b="
B: 
C: ";f s|a:c<-words s=unwords$a:(drop 50s>>b):c

ลองออนไลน์!

  • _:b=" "กำหนดทั้งหมดยกเว้นช่องว่างแรกในสตริงตามตัวอักษรbทำให้เท่ากับสำเนาm mของโปรแกรม
  • sเป็นสตริงอินพุต a:c<-words sแยกออกเป็นคำที่คั่นด้วยช่องว่างเพื่อให้aกลายเป็น A และcกลายเป็นรายการของคำที่ประกอบด้วย C. สำเนา B จะถูกละเว้นตั้งแต่wordsบีบช่องว่างหลาย ๆ (ซึ่งส่วนที่เหลือของโปรแกรมหลีกเลี่ยง)
  • drop 50sคือสตริงที่มีความยาวเท่ากับจำนวนnของสำเนา B ในอินพุต drop 50s>>bเชื่อมต่อหลาย ๆ สำเนาเข้าด้วยbกันทำให้มีช่องว่างmn
  • unwords$a:(drop 50s>>b):cรวมสตริงทั้งหมดเข้าด้วยกันด้วยช่องว่าง เนื่องจากมีคำว่า "พิเศษ" (drop 50s>>b)แทรกอยู่ในรายการจึงมีพื้นที่เข้าร่วมพิเศษเพิ่ม +1 โดยอัตโนมัติในการคูณ

2

Matlab, 85

ครั้งแรกสำหรับฉันที่จะทำสิ่งท้าทายที่เป็นนามธรรมดังนั้นสำหรับฉันมันเป็นความท้าทายในการเขียนโค้ดมากกว่าความท้าทายของรหัส - กอล์ฟ!

สามสายคือไม่มีเครื่องหมายคำพูด:

A:    "X=strsplit(input('','s'));m=0 "
B:    "+1 "
C:    ";[X{1},32,repmat(['+1',32],1,m*(length(X)-2)+1),X{end}]"

วิธีการทำงาน:ฉันแบ่งอาร์กิวเมนต์อินพุตในช่องว่างดังนั้นจึงnสามารถพิจารณาได้จากจำนวนชิ้นส่วนสตริง B mทำงานเป็นจัดเรียงของเคาน์เตอร์ที่จะได้รับ สำหรับการสร้างคำตอบใหม่ฉันใช้ A และ C จากการแบ่งให้ทำซ้ำ B m * n + 1 ครั้งและฉันแทรกช่องว่างโดยใช้ค่า ASCII ของพวกเขาเพื่อไม่ให้เกิดการแยกที่ไม่ต้องการใน C

แก้ไข: อ๊ะนับ A + B โดยไม่ตั้งใจ


1

C (gcc) , 81 ไบต์

ข้อกำหนดในการระบุสตริงดูเหมือนขัดแย้งกับการที่เราได้รับอนุญาตให้ทำงานโดยพลการสำหรับการป้อนข้อมูลที่ผิดกฎหมายเว้นแต่ว่าเราจะมีมาตรฐานที่เข้มงวดในการระบุสิ่งที่ระบุ โดยธรรมชาติแล้วฉันใช้การตีความที่หายไปมากที่สุดไบต์

ลองออนไลน์!

A: m;f(char*s){m=strrchr(s+66,32)-s-65;printf("%.66s%*s",s,m*strlen("
B: <SPACE>
C: ")+16,s+m+66);}

โดยแสดงบัตรประจำตัวฉันเพียงแค่หมายความว่ามันควรจะเป็นที่ชัดเจนจากคำตอบของคุณซึ่งมีโค้ด, BและC มันไม่ใช่ข้อกำหนดสำหรับโปรแกรม
Zgarb

1

TI-Basic (83 ซีรี่ย์) 65 ไบต์

เซกเมนต์ A (33 ไบต์):

Input Str1:sub(Str1,1,27:For(I,0,(length(Str1)-55)(length("

เซกเมนต์ B:

X

เซกเมนต์ C (32 ไบต์):

Y")-1:Ans+"X":End:Ans+sub(Str1,length(Str1)-27,28

ฉันตื่นเต้นมากที่ได้พบกับความท้าทายที่คล้ายกับควินิน! ควนส่วนใหญ่ไม่ทำงานใน TI-Basic โดยไม่มีการโกงอย่างน้อยเพราะไม่มีวิธีการหลบหนี"สัญลักษณ์ (ในทั้งสองความรู้สึกของคำว่า "หลบหนี") แต่ที่นี่เราได้รับสายป้อนข้อมูลผ่านInputคำสั่งและการพิมพ์ใน"นั้นก็ดีมาก

ยังคงมีจำนวนของความโง่ของ TI-Basic ที่จะแก้ไขได้ที่นี่: สตริงว่างเปล่าไม่ถูกต้องดังนั้นวิธีการแก้ปัญหาที่ไร้เดียงสาของการแทรกสตริง"XXX...XX"ในลูปจะไม่ทำงานเมื่อ n = 0 เราคำนวณค่า mn + 1 ด้วยตนเองและใส่สตริง"X"ที่หลาย ๆ ครั้งแทน

ค่าคงที่วิเศษ27และ28ในโปรแกรมเล็กน้อยจากการนับไบต์ 33 และ 32 เพราะStr1, sub(และlength(เป็นราชสกุลสองไบต์เท่านั้นที่มีส่วนร่วม 1 ความยาวของสตริง

หากเราใช้การขึ้นบรรทัดใหม่แทน:ดูเหมือนว่าจะสามารถบันทึกได้สองสามไบต์โดยไม่ต้องใส่เครื่องหมายอัญประกาศที่สิ้นสุด แต่สิ่งนี้ไม่ได้ผล ก่อนอื่นคุณต้องมีตัวแก้ไข hex ก่อนจึงจะสามารถเพิ่มอักขระบรรทัดใหม่ลงในสตริงได้: คุณไม่สามารถพิมพ์ได้เพราะถ้าคุณกด ENTER ระหว่างInputคำสั่งคำสั่งจะส่งอินพุต เมื่อฉันลองใช้ตัวแก้ไขฐานสิบหกฉันลงเอยด้วยข้อผิดพลาดบัฟเฟอร์ล้นที่แก้ไขเนื้อหาของโปรแกรมของฉันดังนั้นอย่าลองทำที่บ้านด้วยเครื่องคิดเลขราคาแพงของคุณ


0

Java 11, 135 65 + 26 = 91 ไบต์

A

s->{var p=s.split("\\(\"|\"\\.");return p[0]+"(\"B"+p[1].repeat("

B

B

C

".length())+'"'+'.'+p[2];}

ลองออนไลน์ได้ที่นี่ (TIO ยังไม่มี Java 11 ดังนั้นสิ่งนี้จึงอาศัยวิธีการช่วยเหลือแทนString::repeat())

Ungolfed:

s -> { // lambda taking and returning a String
    var p = s.split("\\(\"|\"\\."); // split input into parts A, B^n, C (where n may be 0) at the "(\"" and "\"."
    return p[0] + "(\"B" + // put it back together: A plus the part the split shaved off, plus an extra B ...
    p[1].repeat("BBB".length()) + // ... plus B^(n*m)
    '"' + '.' + p[2]; // plus C, with the part the split shaved off reattached
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.