ตรวจสอบโซลูชันหอคอยแห่งฮานอย


29

หากคุณไม่ทราบว่าหอคอยแห่งฮานอยคืออะไรฉันจะอธิบายสั้น ๆ : มีแท่งสามแท่งและแผ่นบางส่วนที่มีขนาดแตกต่างกัน ในการเริ่มต้นแผ่นทั้งหมดอยู่ในหอคอยแรกตามลำดับ: ที่ใหญ่ที่สุดอยู่ที่ด้านล่างที่เล็กที่สุดที่ด้านบน เป้าหมายคือนำแผ่นดิสก์ทั้งหมดไปยังแกนที่สาม ฟังดูง่ายไหม นี่คือการจับ: คุณไม่สามารถวางแผ่นดิสก์ที่ด้านบนของแผ่นดิสก์ที่มีขนาดเล็กกว่าแผ่นดิสก์อื่น คุณสามารถถือแผ่นดิสก์ไว้ในมือของคุณในเวลาเดียวที่จะย้ายพวกเขาไปยังคันอื่นและคุณสามารถวางแผ่นดิสก์บนแท่งเท่านั้นไม่ได้อยู่บนโต๊ะคุณไอ้ขี้ขลาด

โซลูชัน ascii ตัวอย่าง:

  A      B      C
  |      |      |      
 _|_     |      |      
__|__    |      |


  A      B      C
  |      |      |      
  |      |      |      
__|__   _|_     |


  A      B      C
  |      |      |      
  |      |      |      
  |     _|_   __|__


  A      B      C
  |      |      |      
  |      |     _|_     
  |      |    __|__      

ท้าทาย

มีแท่งสามอันเรียกว่า A, B และ C (คุณสามารถเรียกพวกเขา 1,2 และ 3 ได้อย่างเคารพถ้าช่วยได้) ในตอนแรกแผ่น n ทั้งหมดอยู่บนแท่ง A (1)

ความท้าทายของคุณคือการตรวจสอบทางออกสำหรับหอคอยฮานอย คุณจะต้องตรวจสอบให้แน่ใจว่า:

  1. ในตอนท้ายแผ่นดิสก์ทั้งหมดอยู่บนแท่ง C (3)
  2. สำหรับแผ่นดิสก์ใด ๆ ในสถานะที่กำหนดไม่มีดิสก์ขนาดเล็กกว่าด้านล่าง
  3. ไม่มีข้อผิดพลาดที่เห็นได้ชัดเช่นพยายามนำแผ่นดิสก์จากแท่งที่ว่างเปล่าหรือแผ่นดิสก์ที่กำลังเคลื่อนที่ไปยังแท่งที่ไม่มีความยาว

(การแก้ปัญหาไม่จำเป็นต้องดีที่สุด)

อินพุต

โปรแกรมของคุณจะได้รับสองอินพุต:

  1. จำนวนแผ่น n (จำนวนเต็ม)
  2. การเคลื่อนไหวที่ถูกนำมาซึ่งจะประกอบด้วยชุดของ tuples ของ: (หอคอยที่จะนำดิสก์บนสุดในปัจจุบันจาก), (หอคอยที่จะนำดิสก์นี้ไป) ที่แต่ละ tuple หมายถึงการย้าย คุณสามารถเลือกวิธีการแสดง ตัวอย่างเช่นวิธีต่อไปนี้ในการแสดงวิธีแก้ปัญหาสำหรับ n = 2 ที่ฉันวาดใน ascii ด้านบน (ฉันจะใช้ตัวแรกในกรณีทดสอบเพราะมันง่ายต่อการมองเห็น):

    "A-> B; A-> C; B-> C"

    [( "A", "B") ( "A", "C") ( "B", "C")]

    [(1,2), (1,3), (2,3)]

    "ABACBC"

    [1,2,1,3,2,3]

เอาท์พุต

  • ความจริงหากเงื่อนไขที่สามารถพบได้ภายใต้ "ท้าทาย" ถือ

  • เป็นเท็จถ้าไม่

กรณีทดสอบ:

จริง:

n=1, "A->C"

n=1, "A->B ; B->C"

n=2, "A->B ; A->C ; B->C"

n=2, "A->C ; C->B ; A->C ; B->C"

n=2, "A->C ; A->B ; C->B ; B->A ; B->C ; A->C"

n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"

n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C ; B->C"

เท็จ:

รายการที่ 3 แนะนำโดย @MartinEnder, อันดับที่ 7 โดย @Joffan

n=1, "A->B"

n=1, "C->A"

n=2, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"

n=2, "A->B ; A->C ; C->B"

n=2, "A->C ; A->B ; C->B ; B->A"

n=2, "A->C ; A->C"

n=3, "A->B ; A->D; A->C ; D->C ; A->C"

n=3, "A->C ; A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"

n=3, "A->C ; A->B ; C->B ; A->B ; B->C ; B->A ; B->C ; A->C"

n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; C->B"

n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C"

n=4, "A->B ; A->B ; A->B ; A->C ; B->C ; B->C ; B->C"

นี่คือcode-golfทางออกที่สั้นที่สุดชนะ ใช้กฎมาตรฐานและช่องโหว่ ไม่รวมแบตเตอรี่


มันก็ยังโอเคถ้าอินพุต 2 สามารถแสดงโดยใช้วิธีการของคุณ แต่การใช้ตัวเลขแทนตัวอักษร (เช่นA=1, B=2, C=3ฯลฯ )?
R. Kap

1
ฉันขอให้ดัชนีอินพุทเป็นศูนย์ได้ไหม?
Rohan Jhunjhunwala

1
มันจะโอเคไหมถ้ามีข้อผิดพลาดเกิดขึ้นเมื่อดิสก์ถูกนำมาจากแกนที่ว่างเปล่าหรือไม่มีอยู่?
R. Kap

1
เราสามารถคิดได้A->Aไหมว่าจะไม่มีการเคลื่อนไหวที่ไม่เป็นเช่นนั้น?
Martin Ender

2
@Kobi คุณต้องตรวจสอบmoving discs to nonexistant rods.ให้แน่ใจใช่มันเป็นD
edc65

คำตอบ:


7

เรติน่า , 84 80 ไบต์

-5 ไบต์ขอบคุณ Martin Ender

~
 ~$'
$
ABC
{`^(.)(.*)( ~+)\1
$3$2$1
}`^(\W+)(\w)(.*)(?<=\1~+|\w)\2
$3$1$2
^AB 

ลองออนไลน์! (บวก 5 ไบต์สำหรับการทดสอบทีละบรรทัด)

รหัสจำลองเกมเต็ม

  • ACABCBACBABCAC~~~การป้อนข้อมูลจะได้รับเป็น
    ~~~หมายถึงสามแผ่น
  • ACABCBACBABCAC ~~~ ~~ ~ABCครั้งแรกที่สี่บรรทัดแปลงการป้อนข้อมูลในรูปแบบเกม:
    ในตอนแรกก้าน A มีแผ่นทั้ง 3 แผ่นและแท่ง B และ C นั้นว่างเปล่า
  • ต่อไปเราจะวนซ้ำสองขั้นตอน:
    • ใช้ตัวอักษรตัวแรกในบรรทัดซึ่งระบุแท่งตัวถัดไป ค้นหาไม้เท้านี้แล้วนำแผ่นดิสก์แผ่นสุดท้ายออกใส่ตัวอักษรและย้ายแผ่นดิสก์ไปที่สตาร์ก (หยิบขึ้นมา) ในตัวอย่างออกหลังจากขั้นตอนแรกข้อความจะมีลักษณะเช่น:
      ~CABCBACBABCAC ~~~ ~~ABC
    • ในขั้นตอนที่สองเราจะค้นหาแกนเป้าหมายและย้ายแผ่นดิสก์ที่นั่น ABCBACBABCAC ~~~ ~~AB ~Cเราตรวจสอบคันเป็นที่ว่างเปล่าหรือมีแผ่นดิสก์ขนาดใหญ่ที่ด้านบน:
  • ในที่สุดเราก็ยืนยันว่าแท่ง A และ B นั้นว่างเปล่านั่นหมายความว่าแผ่นดิสก์ทั้งหมดอยู่ใน C (มีพื้นที่พิเศษที่บรรทัดสุดท้าย)

ว้าวนั่นน่าประทับใจ
Rohan Jhunjhunwala

17

Retina , 167 165 157 150 123 ไบต์

นี่ดูเหมือนจะเป็นความท้าทายที่ควรได้รับการแก้ไขด้วย regex เดียว ... (แม้จะมีหัวข้อว่า "Retina" นี่เป็นเพียง vanilla .NET regex ซึ่งตรงกับอินพุตที่ถูกต้อง)

^(?=\D*((?=(?<3>1+))1)+)((?=A(?<1-3>.+)|B(?<1-4>.+)|C(?<1-5>.+)).(?=A.*(?!\3)(\1)|B.*(?!\4)(\1)|C.*(?!\5)(\1)).)+(?!\3|\4)1

รูปแบบอินพุตเป็นรายการของคำแนะนำของแบบฟอร์มABตามด้วยในเอกโดยใช้หลักn 1ไม่มีตัวคั่น เอาต์พุตนั้น1ถูกต้องและ0ไม่ถูกต้อง

ลองออนไลน์! (อักขระสองตัวแรกเปิดใช้งานชุดทดสอบที่แยกบรรทัดด้วยฟีด)

โซลูชันทางเลือกนับไบต์เดียวกัน:

^(?=\D*((?=(?<3>1+))1)+)((?=A(?<1-3>.+)|B(?<1-4>.+)|C(?<1-5>.+)).(?=A.*(?!\3)(\1)|B.*(?!\4)(\1)|C.*(?!\5)(\1)).)+(?<-5>1)+$

นี้อาจจะสั้นลงโดยใช้1, 11และ111แทนA, BและCแต่ฉันจะต้องมองเข้าไปในภายหลังว่า มันอาจจะสั้นกว่าที่จะแยกโปรแกรมออกเป็นหลายขั้นตอน แต่ความท้าทายในนั้นอยู่ที่ไหน ;)

คำอธิบาย

วิธีนี้ทำให้การใช้งานหนักของกลุ่มดุล. NET สำหรับคำอธิบายแบบเต็มดูโพสต์ของฉันใน Stack Overflowแต่สาระสำคัญคือกลุ่มการจับภาพใน. NET เป็นสแต็กโดยที่การจับภาพใหม่แต่ละครั้งจะส่งสตริงย่อยอีกอัน สิ่งนี้ช่วยให้คุณนับปริมาณต่าง ๆ ในสตริง ในกรณีนี้มันช่วยให้เราสามารถใช้สามแท่งโดยตรงเป็นกลุ่มการจับภาพที่แตกต่างกันสามกลุ่มซึ่งแต่ละแผ่นจะมีการจับภาพแทน

ในการย้ายแผ่นดิสก์ระหว่างแท่งเราใช้ประโยชน์จากความแปลกประหลาดของ(?<A-B>...)ไวยากรณ์ โดยปกติจะปรากฏการจับภาพจากสแต็กBและกดลงบนสแต็กAสตริงระหว่างการดักจับที่เปิดและเริ่มต้นของกลุ่มนี้ (?<A>a).(?<B-A>c)จับคู่กับดังนั้นabcจะAว่างเปล่าและBกับb(ตรงข้ามกับc) อย่างไรก็ตามเนื่องจากการดูความยาวตัวแปร. NET เป็นไปได้สำหรับการจับ(?<A>...)และ(?<B-A>...)ทับซ้อน สำหรับเหตุผลใดถ้าเป็นกรณีที่จุดตัดBของทั้งสองกลุ่มจะถูกผลักลงบน ฉันได้อธิบายพฤติกรรมนี้ใน "ส่วนขั้นสูง" เกี่ยวกับการสร้างสมดุลของกลุ่มในคำตอบนี้

ในการ regex แท่งA, BและCสอดคล้องกับกลุ่ม3, 4และ5ใน regex ไม่ เริ่มต้นด้วยการเริ่มต้นคันA:

^                 # Ensure that we start at the beginning of the input.
(?=               # Lookahead so that we don't actually move the cursor.
  \D*             # Skip all the instructions by matching non-digit characters.
  (               # For each 1 at the end of the input...
    (?=(?<3>1+))  # ...push the remainder of the string (including that 1)
                  # onto stack 3.
  1)+
)

เช่นถ้าอินพุตสิ้นสุดด้วย111ดังนั้นกลุ่ม 3 / ร็อดAจะเก็บรายการการดักจับไว้[111, 11, 1](ด้านบนอยู่ทางขวา)

รหัสถัดไปมีโครงสร้างดังนี้

(
  (?=A...|B...|C...).
  (?=A...|B...|C...).
)+

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

ขั้นแรกให้นำแผ่นดิสก์ออกจากแกนกำเนิด:

(?=
  A(?<1-3>.+)
|
  B(?<1-4>.+)
|
  C(?<1-5>.+)
)

สิ่งนี้ใช้พฤติกรรมการแยกกลุ่มแปลก ๆ ที่ฉันได้อธิบายไว้ข้างต้น โปรดทราบว่ากลุ่ม3นั้น4และ5จะถือสตริงย่อยของ1s ที่ส่วนท้ายของสตริงที่มีความยาวสอดคล้องกับขนาดของดิสก์ ตอนนี้เราใช้(?<1-N>.+)เพื่อป๊อปแผ่นดิสก์ด้านบนออกจากสแต็คNและกดจุดตัดของสตริงย่อยนี้พร้อมกับจับคู่.+ลงบนสแต็1ก เนื่องจาก.+จำเป็นต้องครอบคลุมการจับทั้งหมดที่โผล่ออกมาNเสมอเราจึงรู้ว่านี่เป็นการย้ายการจับเท่านั้น

ต่อไปเราใส่แผ่นดิสก์นี้จากสแต็ค1ลงบนสแต็กที่สอดคล้องกับแกนที่สอง:

(?=
  A.*(?!\3)(\1)
|
  B.*(?!\4)(\1)
|
  C.*(?!\5)(\1)
)

โปรดทราบว่าเราไม่ต้องล้างสแต็ค1เราสามารถทิ้งแผ่นไว้ที่นั่นเพราะเราจะใส่แผ่นใหม่ไว้ด้านบนก่อนที่จะใช้สแต็คอีกครั้ง นั่นหมายความว่าเราสามารถหลีกเลี่ยงไวยากรณ์และเพียงแค่คัดลอกสตริงมากกว่าด้วย(?<A-B>...) (\1)เพื่อให้มั่นใจว่าการย้ายที่ถูกต้องที่เราใช้ (?!\N)lookahead สิ่งนี้ทำให้มั่นใจได้ว่าจากตำแหน่งที่เราต้องการจับคู่แผ่นดิสก์ในปัจจุบันนั้นเป็นไปไม่ได้ที่จะจับคู่แผ่นดิสก์ที่วางซ้อนNกันอยู่แล้ว สิ่งนี้สามารถเกิดขึ้นได้หาก a) \Nจะไม่ตรงกันเนื่องจากสแต็คนั้นว่างเปล่าหรือ b) the disc on top of stackN is larger than the one we're trying to match with\ 1`

สุดท้ายทั้งหมดที่เหลือจะมั่นใจว่า) เราได้จับคู่คำแนะนำทั้งหมดและ b) แท่งAและที่ว่างเปล่าเพื่อให้ทุกแผ่นได้รับการย้ายไปBC

(?!\3|\4)1

เราก็ตรวจสอบว่าค่า\3มิได้\4สามารถจับคู่ (ซึ่งเป็นเพียงกรณีที่ทั้งสองมีความว่างเปล่าเพราะแผ่นดิสก์ที่เกิดขึ้นจริงใด ๆจะตรง) และที่เรานั้นจะสามารถจับคู่1เพื่อให้เราไม่ได้มองข้ามคำแนะนำใด ๆ


14

Java "เท่านั้น" 311 272 263 261 260 259 256 ไบต์

บันทึก39ไบต์นับไม่ถ้วนเนื่องจาก @Frozn สังเกตเห็นคุณสมบัติการดีบักรุ่นเก่ารวมถึงเทคนิคการเล่นกอล์ฟที่ชาญฉลาด

รุ่น golfed

int i(int n,int[]m){int j=0,k=0,i=n;Stack<Integer>t,s[]=new Stack[3];for(;j<3;)s[j++]=new Stack();for(;i-->0;)s[0].push(i);for(;k<m.length;k+=2)if((t=s[m[k+1]]).size()>0&&s[m[k]].peek()>t.peek())return 0;else t.push(s[m[k]].pop());return s[2].size()<n?0:1;}

ungolfed พร้อมคำอธิบายและสแต็คพิมพ์สวยในแต่ละขั้น

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package codegolf;

/**
 *
 * @author rohan
 */
import java.util.Arrays;
import java.util.Stack;
public class CodeGolf {
    //golfed version
    int i(int n,int[]m){int j=0,k=0,i=n;Stack<Integer>[] s=new Stack[3];for(;j<3;j++)s[j]=new Stack();for(;i-->0;)s[0].push(i);for(;k<m.length;System.out.println(Arrays.toString(s)),k+=2)if(!s[m[k+1]].isEmpty()&&s[m[k]].peek()>s[m[k+1]].peek())return 0;else s[m[k+1]].push(s[m[k]].pop());return s[2].size()==n?1:0;}
    /** Ungolfed
        * 0 as falsy 1 as truthy
        * @param n the number of disks
        * @param m represents the zero indexed stacks in the form of [from,to,from,to]
        * @return 0 or 1 if the puzzle got solved, bad moves result in an exception
        */
    int h(int n, int[] m) {
        //declarations
        int j = 0, k = 0, i = n;
        //create the poles
        Stack<Integer>[] s = new Stack[3];
        for (; j < 3; j++) {
            s[j] = new Stack();
        }
        //set up the first tower using the "downto operator
        for (; i-- > 0;) {
            s[0].push(i);
        }
    //go through and perform all the moves
        for (; k < m.length; System.out.println(Arrays.toString(s)), k += 2) {
            if (!s[m[k + 1]].isEmpty() && s[m[k]].peek() > s[m[k + 1]].peek()) {
                return 0;//bad move
            } else {
                s[m[k + 1]].push(s[m[k]].pop());
            }
        }
        return s[2].size() == n ? 1 : 0;// check if all the disks are done
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
    //test case
        System.out.println( new CodeGolf().h(3,new int[]{0,2,0,1,2,1,0,2,1,0,1,2,0,2})==1?"Good!":"Bad!");
    }

}

เวอร์ชั่นที่ไม่ได้รับการตีพิมพ์นั้นมีคุณสมบัติที่จะพิมพ์สิ่งที่กองที่มีลักษณะเหมือนในแต่ละขั้นตอนเช่นนั้น ...

[[2, 1], [], [0]]
[[2], [1], [0]]
[[2], [1, 0], []]
[[], [1, 0], [2]]
[[0], [1], [2]]
[[0], [], [2, 1]]
[[], [], [2, 1, 0]]
Good!

อะไรSystem.out.println(Arrays.toString(s))ทำอย่างไร
Frozn

มันจะพิมพ์สแต็คค่อนข้างสวย ชอบ [[2,1,0], [] []]
Rohan Jhunjhunwala

Whoops @ Frozn ที่เป็นคุณลักษณะการดีบักลบออกตอนนี้
Rohan Jhunjhunwala

ฉันรู้ว่าเพียงแค่สงสัยว่าทำไมมันมี :) นอกจากนี้คุณยังสามารถแทนที่ด้วย&& &
Frozn

@ Frozn ฉันไม่สามารถแทนที่สิ่งที่น่าเศร้าเพราะฉันอาศัยพฤติกรรมการลัดวงจรเพื่อหลีกเลี่ยงการพยายามมองดูที่กองที่ว่างเปล่า ขอบคุณสำหรับการลดขนาด 39 ไบต์
Rohan Jhunjhunwala

9

Python 2, 186 167 158 135 127 115 110 102 ไบต์

n,m=input()
x=[range(n),[],[]]
for a,b in m:p=x[a].pop();e=x[b];e and 1/(p>e[-1]);e+=p,
if x[0]+x[1]:_

รับอินพุตบน STDIN ในรูปแบบต่อไปนี้:

(1,[(0,1),(1,2)])

นั่นคือ tuple หลามของจำนวนแผ่นและรายการหลามของ tuples (from_rod,to_rod)ของ เช่นเดียวกับใน Python วงเล็บล้อมรอบเป็นทางเลือก ร็อดจะถูกจัดทำดัชนีเป็นศูนย์

ตัวอย่างเช่นกรณีทดสอบนี้:

n=2; "A->B ; A->C ; B->C"

จะได้รับเป็น:

(2,[(0,1),(0,2),(1,2)])

หากวิธีการแก้ปัญหาที่ถูกต้องออกอะไรและออกด้วยรหัสทางออกที่ 0 หากมันไม่ถูกต้องโยนข้อยกเว้นและออกด้วยรหัสทางออกที่ 1 ขว้างIndexErrorถ้าย้ายไปยังแกนที่ไม่มีความยาวหรือพยายามที่จะเอาแผ่นดิสก์ออก ก้านที่ไม่มีแผ่นดิสก์อยู่ZeroDivisionErrorถ้าแผ่นดิสก์วางอยู่ด้านบนของแผ่นดิสก์ที่มีขนาดเล็กลงหรือNameErrorถ้ามีแผ่นดิสก์เหลืออยู่บนแท่งแรกหรือแท่งที่สองในตอนท้าย

บันทึกแล้ว 13 ไบต์ขอบคุณ @KarlKastor!

บันทึกแล้ว 8 ไบต์ขอบคุณ @xnor!


1
การตรวจสอบว่าแต่ละกองมีการเรียงลำดับดูเหมือนซับซ้อนเกินไป คุณไม่สามารถตรวจสอบว่าดิสก์ที่ย้ายมีขนาดใหญ่กว่าดิสก์ด้านบนของกองที่ย้ายไปหรือไม่
xnor

@ xnor ขอบคุณที่ควรจะทำงาน เพิ่มตอนนี้
ทองแดง

5

Python 2.7, 173 158 138 130 127 123 ไบต์:

r=range;a,b=input();U=[r(a,0,-1),[],[]]
for K,J in b:U[J]+=[U[K].pop()]if U[J]<[1]or U[K]<U[J]else Y
print U[-1]==r(a,0,-1)

รับอินพุตผ่าน stdin ในรูปแบบ(<Number of Discs>,<Moves>)ที่<Moves>กำหนดเป็นอาร์เรย์ที่มี tuples ที่สอดคล้องกับการย้ายแต่ละครั้งซึ่งแต่ละคู่มีจำนวนเต็มคั่นด้วยเครื่องหมายจุลภาค ตัวอย่างเช่นกรณีทดสอบ:

n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C" 

รับในโพสต์จะได้รับเป็น:

(3,[(0,2),(0,1),(2,1),(0,2),(1,0),(1,2),(0,2)]) 

ในโปรแกรมของฉัน ส่งออกIndexErrorเงื่อนไขถ้าไม่พบเงื่อนไขที่ 3 a NameErrorหากเงื่อนไขที่สองไม่เป็นไปตามเงื่อนไขและFalseหากไม่ได้ปฏิบัติตามเงื่อนไขข้อที่ 1 Trueมิฉะนั้นผล


สองสิ่ง: ตัวแปรYไม่เคยถูกกำหนดในโค้ดของคุณ (ฉันคิดว่าควรเป็น J) และU[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]สั้นกว่า 3 ตัวอักษรที่stmt1 if cond else stmt2
jermenkoo

@ jermenkoo ดีฉันใช้Yตัวแปรเช่นนั้นคือการเพิ่มNameErrorเมื่อใดก็ตามที่เงื่อนไขที่สองไม่เป็นไปตาม ถ้าฉันจะเปลี่ยนYไปJแล้วก็NameErrorจะไม่ถูกยกขึ้น ด้วยเหตุนี้ฉันจึงไม่สามารถทำเช่นU[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]นี้ได้เพราะมันจะเพิ่มขึ้นNameError ตลอดเวลาไม่ใช่แค่เมื่อเงื่อนไขข้อที่สองไม่เป็นไปตาม
R. Kap

เอาล่ะขอบคุณสำหรับคำอธิบายของคุณ!
jermenkoo

5

VBA, 234 217 213 196 ไบต์

Function H(N,S)
ReDim A(N)
While P<Len(S)
P=P+2:F=1*Mid(S,P-1,1):T=1*Mid(S,P,1)
E=E+(T>2):L=L+T-F
For i=1 To N
If A(i)=F Then A(i)=T:Exit For
E=E+(A(i)=T)+(i=N)
Next
Wend
H=L+9*E=2*N
End Function

รูปแบบอินพุตสำหรับการย้ายคือสตริงที่มีจำนวนหลัก (012) การเรียกใช้อยู่ในสเปรดชีต = H ([จำนวนดิสก์], [สตริงย้าย])

อาเรย์ A ถือตำแหน่งคันของแผ่นดิสก์ต่าง ๆ การย้ายเป็นเพียงการอัพเดทครั้งแรกของหมายเลขแท่ง "จาก" เป็นหมายเลขแท่ง "ถึง" หากคุณพบแผ่นร็อด "ถึง" ก่อนหรือไม่มีแผ่นดิสก์ "จาก" แสดงว่าเป็นการย้ายที่ไม่ถูกต้อง "ค่าร็อด" ทั้งหมดของ A เก็บไว้ใน L ซึ่งต้องสิ้นสุดที่ 2N ข้อผิดพลาดจะถูกสะสมเป็นจำนวนลบใน E

เหมือนกับการแก้ปัญหาอื่น ๆ การ "ย้าย" แผ่นดิสก์จากหอคอยไปยังหอคอยเดียวกันนั้นไม่ได้รับอนุญาต ฉันสามารถห้ามมันได้อีก 6 ไบต์

ผล

ผลลัพธ์ฟังก์ชั่นในคอลัมน์แรก (กรณีสุดท้าย n = 3 คือการเพิ่มของฉันโดยใช้แท่งพิเศษ)

TRUE    1   02
TRUE    1   0112
TRUE    2   010212
TRUE    2   02210212
TRUE    2   020121101202
TRUE    3   02012102101202
TRUE    4   010212012021010212102012010212

FALSE   1   01
FALSE   1   20
FALSE   2   02012102101202
FALSE   2   010221
FALSE   2   02012110
FALSE   2   0202
FALSE   3   0202012102101202
FALSE   3   0201210112101202
FALSE   3   02012102101221
FALSE   3   0103023212
FALSE   4   0102120120210102121020120102
FALSE   4   01010102121212

2

php, 141 ไบต์

<?php $a=$argv;for($t=[$f=range($a[++$i],1),[],[]];($r=array_pop($t[$a[++$i]]))&&$r<(end($t[$a[++$i]])?:$r+1);)$t[$a[$i]][]=$r;echo$t[2]==$f;

สคริปต์บรรทัดคำสั่งใช้อินพุตเป็นความสูงจากนั้นชุดของดัชนีอาร์เรย์ (0 ที่จัดทำดัชนี) เช่น 1 0 2 หรือ 2 0 1 0 2 1 2 สำหรับกรณีทดสอบที่สั้นที่สุดของความสูง 1 หรือ 2
Echos 1 ในกรณีจริงและไม่มีอะไรผิดพลาด
ให้ 2 ประกาศและ 1 คำเตือนดังนั้นจำเป็นต้องเรียกใช้ในสภาพแวดล้อมที่เงียบเสียงเหล่านั้น


1

JavaScript (ES6), 108

n=>s=>!s.some(([x,y])=>s[y][s[y].push(v=s[x].pop())-2]<v|!v,s=[[...Array(s=n)].map(_=>s--),[],[]])&s[2][n-1]

รูปแบบอินพุต:ฟังก์ชั่นที่มี 2 ข้อโต้แย้ง

  • หาเรื่อง 1, ตัวเลข, จำนวนของวง
  • arg 2, อาร์เรย์ของสตริง, แต่ละสตริง 2 อักขระ '0', '1', '2'

เอาท์พุท:คืน 1 ถ้าตกลง, 0 ถ้าไม่ถูกต้อง, ยกเว้นถ้าไม่มีแกนเหล็ก

หักกอล์ฟแล้วอธิบาย

n=>a=>(
  // rods status, rod 0 full with an array n..1, rod 1 & 2 empty arrays
  s = [ [...Array(t=n)].map(_=>t--), [], [] ],
  // for each step in solution, evaluate function and stop if returns true
  err = a.some( ([x,y]) => {
    v = s[x].pop(); // pull disc from source rod
    // exception is s[x] is not defined
    if (!v) return 1; // error source rod is empty
    l = s[y].push(v); // push disc on dest rod, get number of discs in l
    // exception is s[y] is not defined
    if(s[y][l-2] < v) return 1; // error if undelying disc is smaller
  }),
  err ? 0 // return 0 if invalid move
  : s[2][n-1]; // il all moves valid, ok if the rod 2 has all the discs
)

หมายเหตุการทดสอบ : จำเป็นต้องใช้แถวแรกของฟังก์ชั่นทดสอบเพื่อแปลงรูปแบบอินพุตที่กำหนดในคำถามเป็นอินพุตที่ฟังก์ชันของฉันคาดหวัง

F=
n=>s=>!s.some(([x,y])=>s[y][s[y].push(v=s[x].pop())-2]<v|!v,s=[[...Array(s=n)].map(_=>s--),[],[]])&s[2][n-1]

Out=x=>O.textContent+=x+'\n'

Test=s=>s.split`\n`.map(r=>[+(r=r.match(/\d+|.->./g)).shift(),r.map(x=>(parseInt(x[0],36)-10)+''+(parseInt(x[3],36)-10))])
.forEach(([n,s],i)=>{
  var r
  try {
    r = F(+n)(s);
  } 
  catch (e) {
    r = 'Error invalid rod';
  }
  Out(++i+' n:'+n+' '+s+' -> '+r)
})

Out('OK')
Test(`n=1, "A->C"
n=1, "A->B ; B->C"
n=2, "A->B ; A->C ; B->C"
n=2, "A->C ; C->B ; A->C ; B->C"
n=2, "A->C ; A->B ; C->B ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C ; B->C"`)

Out('\nFail')
Test( `n=1, "A->B"
n=1, "C->A"
n=2, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=2, "A->B ; A->C ; C->B"
n=2, "A->C ; A->B ; C->B ; B->A"
n=2, "A->C ; A->C"
n=3, "A->B ; A->D; A->C ; D->C ; A->C"
n=3, "A->C ; A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->B ; B->C ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; C->B"
n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C"
n=4, "A->B ; A->B ; A->B ; A->C ; B->C ; B->C ; B->C"`)
<pre id=O></pre>

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