โค่นล้มโดมิโน!


22

ขอบคุณคำถามนี้สำหรับแรงบันดาลใจบางอย่าง

ในความท้าทายนี้เราจะเป็นตัวแทนของสายของแต้มเป็นสตริงของที่|, และ/ \คุณจะได้รับสายอักขระโดมิโนเป็นอินพุตและคุณต้องพิจารณาสิ่งที่พวกเขาดูเหมือนเมื่อพวกเขาได้ตัดสิน นี่คือกฎสำหรับแต้มที่ตกลงมา

  • โดมิโนที่ยืนอยู่|, ซ้ายของโดมิโนที่ล้มลงทางซ้าย\, จะกลายเป็นโดมิโนที่ล้มลงด้วยเช่นกัน

  • โดมิโนที่ยืนอยู่|ด้านขวาของโดมิโนที่ถูกตก/จะกลายเป็นโดมิโนที่ตกลงมาอย่างถูกต้องเช่นกัน

  • หากโดมิโนยืนอยู่ระหว่างซ้าย\และขวาตก/โดมิโนมันจะยังคงยืนอยู่

กฎเหล่านี้จะถูกนำมาใช้ซ้ำ ๆ จนกระทั่งข้อตกลงไม่เปลี่ยนแปลงอีกต่อไป

นี่คือตัวอย่างของวิธีการป้อนข้อมูลเดียวอาจมาถึงข้อสรุปของมัน

|||||||\/|||||||\||\|||/||||||\|||||

||||||\\//|||||\\|\\|||//||||\\|||||
|||||\\\///|||\\\\\\|||///||\\\|||||
||||\\\\////|\\\\\\\|||////\\\\|||||
|||\\\\\////|\\\\\\\|||////\\\\|||||
||\\\\\\////|\\\\\\\|||////\\\\|||||
|\\\\\\\////|\\\\\\\|||////\\\\|||||

\\\\\\\\////|\\\\\\\|||////\\\\|||||

งานของคุณคือการเขียนโค้ดที่ค้นหาและแสดงผลลัพธ์สุดท้ายของอินพุต คุณอาจสมมติว่าอินพุตนั้นถูกต้องเสมอและมีอย่างน้อย 2 ตัวอักษร

นี่คือดังนั้นคำตอบจะได้คะแนนเป็นไบต์ด้วยจำนวนไบต์ที่น้อยกว่าจะดีกว่า

กรณีทดสอบ

|||/||||  -> |||/////
|||\||||  -> \\\\||||
|/||||\|  -> |///\\\|
||/|||\|  -> ||//|\\|
||\|||/|  -> \\\|||//

6
ทับขวาหลบหนี ahoy! (เราจะใช้สัญลักษณ์อื่นได้ไหม?)
Arnauld

1
@Arnauld ไม่คุณควรใช้เครื่องหมายทับ
ข้าวสาลีตัวช่วยสร้าง

1
ฉันไม่สามารถคิดออกว่าจะหนีอะไรและอะไรจะทำไม่ได้
มนุษย์โดยรวม

อินพุตจะเป็นสตริงว่างหรืออักขระเดี่ยวหรือไม่
Doorknob

3
มันรบกวนจิตใจฉันมากกว่าที่ควรจะเป็นสิ่งที่ `//////// | \ ถือว่ามีเสถียรภาพ
MooseBoys

คำตอบ:


13

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

+`(/.\\)|(/)\||\|(\\)
$1$2$2$3$3

ลองออนไลน์!

คำอธิบาย

+บอก Retina ที่จะเรียกใช้ทดแทนในวงจนกว่าจะล้มเหลวในการเปลี่ยนสตริง การเปลี่ยนแต่ละครั้งจะคำนวณโดมิโนที่ล้มลงในขั้นตอนเดียว การเปลี่ยนตัวเองเป็นสามการแทนที่ในครั้งเดียว แต่สิ่งนี้ทำให้มั่นใจได้ว่าจะเกิดขึ้นพร้อมกัน:

(/.\\)...
$1

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

...(/)\|...
$2$2

แมตช์นี้และเปลี่ยนมันเป็น/|//

...\|(\\)
$3$3

แมตช์นี้และเปลี่ยนมันเป็น|\\\


ไม่สามารถพูดได้ว่าฉันไม่เห็นว่ามา Retina แน่นอนว่าเป็นเครื่องมือที่ดีสำหรับงาน
ข้าวสาลีตัวช่วยสร้าง

@WeatWizard ง่ายต่อการแก้ไข แต่อาจจะยังละเอียดเกินไปกับการหลบหนีทั้งหมดและที่$1$2$2$3$3จะเอาชนะภาษากอล์ฟ
Martin Ender


4

V , 23 ไบต์

òÓ¯À<!|¨Ü©ü¨¯©|ÜÀ!/±±²²

ลองออนไลน์!

จริง ๆ แล้วมันคล้ายกับคำตอบของเรตินา ใช้การบีบอัด regex

hexdump:

00000000: f2d3 afc0 3c21 7ca8 dca9 fca8 afa9 7cdc  ....<!|.......|.
00000010: c021 2fb1 b1b2 b2                        .!/....

คำอธิบาย:

òบอกให้ V รันจนกว่าสตริงจะไม่เปลี่ยน ส่วนที่เหลือเป็น regex ที่ถูกบีบอัด ลองแปลงเป็นค่าที่เป็นกลุ่ม ...

:s/\v\/@<!\|(\\)|(\/)\|\\@!/\1\1\2\2/g

:s/                                     " Substitute...
   \v                                   " Turn on magic (use less escaping)
          \|                            " A bar
            (\\)                        " Followed by a captured backslash
       @<!                              " That is not preceded by
     \/                                 " A forward slash
                |                       " OR...
                 (\/)                   " A captured forward slash
                     \|                 " Followed by a bar
                       \\@!             " That is not followed by a backslash
                           /            " Replace this with
                            \1\1        " Pattern 1 twice (will be empty if we matched the second path)
                                \2\2    " Pattern 2 twice (will be empty if we matched the first path)
                                    /g  " Replace every match on this line

4

SNOBOL4 (CSNOBOL4) , 117 115 112 111 ไบต์

	D =INPUT
S	D '/|\' ='_'	:S(S)
	E =D
	D '/|' ='//'
	D '|\' ='\\'
	D E	:F(S)
R	D '_' ='/|\'	:S(R)
	OUTPUT =D
END

ลองออนไลน์!

เครดิตเพื่อตอบหลามก้านD '/|' | '|\'สำหรับความคิดสำหรับสภาพหยุดกับตัวแปรที่สองที่จะเห็นการเปลี่ยนแปลงที่มากกว่าการทดสอบ

	D =INPUT		;* read input
S	D '/|\' ='_'	:S(S)	;* replace '/|\' with '_', recursively
	E =D			;* set E to D, this is the while loop
	D '/|' ='//'		;* topple right
	D '|\' ='\\'		;* topple left
	D E	:F(S)		;* if D doesn't match E, goto S
R	D '_' ='/|\'	:S(R)	;* replace '_' with '/|\' (inverse of statement S)
	OUTPUT =D		;* output
END

3

Haskell , 114 107 ไบต์

until=<<((==)=<<)$g
g s=t<$>zip3('|':s)s(tail s++"|")
t(l,'|',r)|l<'0',r/='\\'=l|r=='\\',l>'/'=r
t(_,e,_)=e

ลองออนไลน์! บรรทัดแรกกำหนดฟังก์ชั่นที่ไม่ระบุชื่อ

คำอธิบาย:

  • until=<<((==)=<<)$gเป็นฟังก์ชั่นแก้ไขจุด (ดูที่นี่สำหรับคำอธิบาย) ซึ่งใช้ฟังก์ชั่นgกับสายป้อนข้อมูลจนกว่าผลลัพธ์จะไม่เปลี่ยนแปลงอีกต่อไป
  • zip3('|':s)s(tail s++"|")สร้างขึ้นสำหรับโดมิโนแต่ละตัวนั่นคือตัวละครในสตริงsสามกับโดมิโนก่อนและประสบความสำเร็จซ้อนกับ|ขอบ เช่น/\|จะกลายเป็น[(|,/,\),(/,\,|),(\,|,|)](ละเว้นการหลบหนี)
  • จากนั้นฟังก์ชั่นtจะถูกนำไปใช้กับแต่ละอเนกประสงค์เพื่อคำนวณตำแหน่งใหม่ของชิ้นกลางของสาม


2

Prolog (SWI) , 132 ไบต์

+[]-->[].
+[47,124,92|T]-->"/|\\",+T.
+[47,47|T]-->"/|",+T.
+[92,92|T]-->"|\\",+T.
+[X|T]-->[X],+T.
X+Y:- +(N,X,[]),!,(X=N,Y=N;N+Y).

ลองออนไลน์!

โปรแกรมนี้กำหนดเพรดิเคต+/2ที่เป็นจริงหากอาร์กิวเมนต์ที่สองเป็นเวอร์ชันที่ถูกตัดสินของครั้งแรก อาร์กิวเมนต์ทั้งสองเป็นรายการของรหัสอักขระ

คำอธิบาย

โซลูชันนี้ใช้ DCG เพื่อค้นหาว่าขั้นตอนต่อไปคืออะไรแล้วจึงคำนวณขั้นตอนถัดไปซ้ำ ๆ จนกระทั่งขั้นตอนถัดไปเหมือนกับขั้นตอนปัจจุบัน

DCG

+[]-->[].
+[47,124,92|T]-->"/|\\",+T.
+[47,47|T]-->"/|",+T.
+[92,92|T]-->"|\\",+T.
+[X|T]-->[X],+T.

โค้ดห้าบรรทัดเหล่านี้กำหนดกฎ DCG (Definite Clause Grammar) +ที่ใช้ในโปรแกรมเพื่อคำนวณขั้นตอนเดียวในการแต้มโดมิโน DCGs ใน Prolog ทำงานโดยการค้นหากรณีแรกของกฎที่ด้านขวามือตรงกับสตริงและกำหนดอาร์กิวเมนต์ของกฎทางด้านซ้ายมือผ่านกระบวนการนั้น หากกรณีและปัญหาไม่ตรงกันจะมีการย้อนรอยและลองกรณีใหม่

+[]-->[].

บรรทัดนี้แสดงถึงกรณีฐานของ+กฎ มันก็บอกว่าถ้าไม่มีโดมิโนในขั้นตอนต่อไปก็จะไม่มีโดมิโน

+[47,124,92|T]-->"/|\\",+T.

เนื่องจากโปรแกรมนี้เกี่ยวเฉพาะกับรายการของรหัสตัวละครมันเป็นสิ่งสำคัญที่จะทราบว่ารหัสตัวอักษรสำหรับ/, \และ|47, 92 และ 124 ตามลำดับ กรณีของ+กฎนี้จัดการ/|\สตริง

+[47,47|T]-->"/|",+T.

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

+[92,92|T]-->"|\\",+T.

จัดการกรณีสำหรับโดมิโนที่ตกลงมาทางซ้ายกระแทกโดมิโนไปทางซ้ายของมัน

+[X|T]-->[X],+T.

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

ภาคแสดง

X+Y:- +(N,X,[]),!,(X=N,Y=N;N+Y).

เพรดิเคตหลักใช้เวลาสองอาร์กิวเมนต์แรกคือการตั้งค่าเริ่มต้นโดมิโนที่สองคือการตัดสินโดมิโน เนื่องจากนี่คือ Prolog โปรแกรมที่สองสามารถไม่สามารถระบุได้และโปรแกรมจะคำนวณ คำกริยาและของตัวเองค่อนข้างง่าย+(N,X,[])โทร DCG Nและคำนวณขั้นตอนต่อไปของการแต้มเก็บไว้ใน (X=N,Y=N;N+Y)ตรวจสอบว่าขั้นตอนต่อไปของแต้มเป็นเช่นเดียวกับในปัจจุบันและถ้ามันเป็นมันชุดYไปตั้งแต่แต้มจะต้องมีการตัดสินและถ้ามันไม่ได้ recurses เรียกกริยาเช่นเดียวกันกับขั้นตอนต่อไปของแต้มแทนNX



1

ใบหน้า 166 ไบต์

\|/,cm_/o>AvI[IIcP/+PP|m_/m*/Sl*Im1/11:~-_I|'|?_1-_P|?_1`I-III_|+II|'I.C:1-_I|?_C'|-_P|?_C_|'I-_I|`I?_!'I.C:!'|'|-III+II|'I:C_|-PPP+PPI'I?I~_I-PPP+PP|-**1?*~Sl*Iw*I*>

รับอินพุตเป็นอาร์กิวเมนต์บรรทัดรับคำสั่งและส่งออกไปยัง STDOUT ใช้งานได้ในการส่ง 86494f6 และเกินกว่านั้นเนื่องจากข้อผิดพลาดในการส่ง

ห่อเพื่อความสวยงาม:

\|/,cm_/o>AvI[IIcP/+PP|m_/m*/Sl*Im1/11:~-_I|'|?_1-_P|?_1`I
-III_|+II|'I.C:1-_I|?_C'|-_P|?_C_|'I-_I|`I?_!'I.C:!'|'|-III
+II|'I:C_|-PPP+PPI'I?I~_I-PPP+PP|-**1?*~Sl*Iw*I*>

และไม่สุภาพ / แสดงความคิดเห็น:

\|/,cm_/o>              ( setup )

AvI[II                  ( store input into I )
cP/+PP|m_/              ( store 92, ascii for \, into P, meaning prev char )
m*/Sl*Im1/11            ( store length of input into counter variable * )

( main loop: )
:~

    -_I|'|?_1           ( branch to 1 if the character is not \ )
    -_P|?_1             ( also branch to 1 if the previous character wasn't | )
    `I-III_|+II|'I      ( we have a sequence |\ so prev needs to be toppled )
    .C                  ( jump to C, the "continue" label at end of loop )

    :1
    -_I|?_C             ( branch to C if the character is not | )
    '|-_P|?_C           ( also branch to C if the previous character wasn't / )
    _|'I-_I|`I?_!       ( branch to ! if the next character isn't \ )
    'I.C:!              ( otherwise, skip the next \ and branch to continue )
    '|'|-III+II|'I      ( if all conditions hold we have /|| or /|/ so topple )

    :C
    _|                  ( reset pointer to source )
    -PPP+PPI            ( update prev variable )
    'I                  ( step through data )

?I~

_I-PPP+PP|-**1          ( reset input/prev and decrement counter )
?*~                     ( repeat main loop as many times as there are chars )

Sl*Iw*I*>               ( output final string to stdout )

มีเคล็ดลับเล็ก ๆ น้อย ๆ อยู่ที่นี่เพื่อกำจัดส่วนเกินพิเศษไม่กี่ไบต์เช่น

  • การตั้งชื่อของตัวแปร | และ / ซึ่งมีการเข้าถึงค่า ASCII ผ่านการวิปัสสนาภายหลังในรหัส

  • '|ในบรรทัดแรกของวงหลักซึ่งเรียกว่ามีแทนในบรรทัดที่สองเพื่อตั้ง | ตัวชี้สำหรับใช้ในส่วนที่สองของลูปหลัก


1

Perl 5 , 52 + 1 (-p) = 53 ไบต์

-6 ไบต์ขอบคุณ mik

อาจไม่ใช่สิ่งที่ดีที่สุดสำหรับ Perl แต่เป็นสิ่งที่ฉันสามารถทำได้

0while(s/(?<!\/)\|(?=(\\))|(?<=(\/))\|(?!\\)/$1$2/g)

คำอธิบาย

while(
  s/
    (?<!\/)\|(?=(//)) # If there's a | that precedes a \ but doesn't follow a /, capture /
      | # Or
    (?<=(\/))\|(?!//)/ # If there's a | that follows a / doesn't precede a \, capture /
  /$1$2/ # Replace all | with capture group 1 or 2, as one of the two will always be empty
  g # Repeat as much as possible for this string
)

ลองออนไลน์!


-pแทนการ-aลดความต้องการprint;; การใช้whileเป็นคำต่อท้ายไปยังนิพจน์จำลอง (เช่น0) จะช่วยเพิ่ม 2 ไบต์อีกครั้ง
mik

ขอบคุณ @mik ฉันไม่ทราบเทคนิคเหล่านั้น ฉันยังตระหนักว่าฉันสามารถคั่น regex ด้วยสิ่งอื่นเพื่อบันทึกไบต์ อาจจะได้รับในภายหลัง
เจฟฟรีย์เอช

1

Perl 5 , 44 (รหัส) + 1 ( -p) = 45 ไบต์

1while s,(/)\|(?!\\)|(?<!/)\|(\\),$1$1$2$2,g

ลองออนไลน์!

คำอธิบาย

1while s,                        ,        ,g   while anything found substitute globally
         (/)\|(?!\\)              $1$1         /| that is not followed by \ to //
                    |                          or
                     (?<!/)\|(\\)     $2$2     |\ that is not preceded by / to \\


0

Ruby , 83 ไบต์

โกงด้วยเทคนิค9.timesหรือแม้แต่แค่999.timesแต่ฉันไม่รู้สึกว่าถูก :)

ยังคงมีศักยภาพในการเล่นกอล์ฟขนาดใหญ่ (หมายเหตุ: y while undoneยาวกว่าx.size.times)

->x{x.size.times{x.gsub! /\/\|\\?|\|\\/,'/|\\'=>'/|\\','/|'=>'//','|\\'=>'\\\\'}
x}

ลองออนไลน์!



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