Xác minh giải pháp Tháp Hà Nội


29

Nếu bạn không biết Tháp Hà Nội là gì, tôi sẽ giải thích ngắn gọn: Có ba thanh và một số đĩa có kích thước khác nhau. Ban đầu, tất cả các đĩa đều nằm trên tháp đầu tiên, theo thứ tự được sắp xếp: Cái lớn nhất nằm ở dưới cùng, nhỏ nhất ở trên cùng. Mục tiêu là đưa tất cả các đĩa qua thanh thứ ba. Nghe có vẻ dễ dàng? Đây là một nhược điểm: Bạn không thể đặt một đĩa lên trên một đĩa nhỏ hơn đĩa khác; bạn chỉ có thể cầm một đĩa trong tay một lúc để di chuyển chúng sang một thanh khác và bạn chỉ có thể đặt đĩa lên que chứ không phải trên bàn, bạn lén lút.

giải pháp ví dụ ascii:

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


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


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


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

Thử thách

Có ba thanh được gọi là A, B và C. (Bạn cũng có thể gọi chúng là 1,2 và 3 một cách tôn trọng nếu điều đó có ích) Lúc đầu, tất cả n đĩa đều nằm trên thanh A (1).

Thách thức của bạn là xác minh một giải pháp cho tòa tháp hà nội. Bạn sẽ cần đảm bảo rằng:

  1. Cuối cùng, tất cả n đĩa đều nằm trên thanh C (3).
  2. Đối với bất kỳ đĩa nhất định tại bất kỳ trạng thái nhất định, không có đĩa nhỏ hơn bên dưới nó.
  3. Không có lỗi rõ ràng như cố gắng lấy đĩa từ một thanh trống hoặc di chuyển đĩa sang thanh không tồn tại.

(giải pháp không phải là tối ưu.)

Đầu vào

Chương trình của bạn sẽ nhận được hai đầu vào:

  1. Số lượng đĩa n (một số nguyên)
  2. Các động tác được thực hiện, sẽ bao gồm một bộ các bộ dữ liệu: (tháp để lấy đĩa cao nhất hiện tại), (tháp để đưa đĩa này đến) trong đó mỗi bộ dữ liệu đề cập đến một di chuyển. Bạn có thể chọn cách chúng được đại diện. Ví dụ, một cái gì đó giống như các cách biểu diễn giải pháp sau đây cho n = 2 mà tôi đã vẽ ở ascii ở trên. (Tôi sẽ sử dụng cái đầu tiên trong các trường hợp thử nghiệm, vì nó dễ nhìn):

    "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]

Đầu ra

  • Sự thật, nếu các điều kiện có thể được tìm thấy trong "thách thức" giữ.

  • Falsy, nếu họ không.

Các trường hợp thử nghiệm:

Thật:

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"

Sai:

Cái thứ 3 được đề xuất bởi @MartinEnder, thứ 7 bởi @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"

Đây là mã golf , giải pháp ngắn nhất thắng. Quy tắc tiêu chuẩn và sơ hở áp dụng. Không có pin bao gồm.


Là nó cũng không sao nếu đầu vào thứ 2 có thể được biểu diễn bằng phương pháp của bạn, nhưng sử dụng số thay vì chữ cái (tức là A=1, B=2, C=3, vv)?
R. Kap

1
Tôi có thể lập chỉ mục đầu vào không?
Rohan Jhunjhunwala

1
Có ổn không nếu một lỗi được ném khi một đĩa được lấy từ một thanh trống hoặc không tồn tại?
R. Kap

1
Chúng ta có thể cho rằng sẽ không có di chuyển như thế A->Anào không?
Martin Ender

2
@Kobi bạn phải kiểm tra moving discs to nonexistant rods.vì vậy tất nhiên là có, đó làD
edc65

Câu trả lời:


7

Võng mạc , 84 80 byte

-5 byte nhờ Martin Ender

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

Hãy thử trực tuyến! (cộng thêm 5 byte cho các bài kiểm tra từng dòng)

Mã mô phỏng một trò chơi đầy đủ.

  • Đầu vào được đưa ra là ACABCBACBABCAC~~~.
    ~~~nghĩa là ba đĩa.
  • Bốn dòng đầu tiên chuyển đổi đầu vào thành định dạng trò chơi : ACABCBACBABCAC ~~~ ~~ ~ABC.
    Ban đầu, thanh A có tất cả 3 đĩa và thanh B và C trống.
  • Tiếp theo chúng ta có một vòng gồm hai bước:
    • Lấy chữ cái đầu tiên trong dòng, cho biết thanh nguồn tiếp theo. Tìm thanh này và lấy đĩa cuối cùng vào. Xóa chữ cái và di chuyển đĩa đến thân cây (nhặt nó lên).
      Trong ví dụ, sau bước đầu tiên, văn bản sẽ trông như : ~CABCBACBABCAC ~~~ ~~ABC.
    • Trong giai đoạn thứ hai, chúng tôi tìm thấy thanh đích và di chuyển đĩa đến đó. Chúng tôi xác nhận thanh trống hoặc có đĩa lớn hơn ở đầu : ABCBACBABCAC ~~~ ~~AB ~C.
  • Cuối cùng, chúng tôi xác nhận thanh A và B trống - điều này có nghĩa là tất cả các đĩa đều ở C (có thêm khoảng trống ở dòng cuối cùng).

Wow, thật ấn tượng
Rohan Jhunjhunwala

17

Võng mạc , 167 165 157 150 123 byte

Điều này hoàn toàn giống như một thách thức cần được giải quyết với một regex duy nhất ... (mặc dù tiêu đề có nội dung "Retina", đây chỉ là một regex .NET vanilla, phù hợp với các đầu vào hợp lệ).

^(?=\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

Định dạng đầu vào là danh sách các hướng dẫn của biểu mẫu AB, theo sau là nunary sử dụng chữ số 1. Không có dải phân cách. Đầu ra là 1hợp lệ và 0không hợp lệ.

Hãy thử trực tuyến! (Hai ký tự đầu tiên kích hoạt bộ kiểm tra phân tách dòng cấp.)

Giải pháp thay thế, cùng số byte:

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

Điều này có thể có thể được rút ngắn bằng cách sử dụng 1, 11111thay vì A, BCnhưng tôi sẽ phải nhìn vào mà sau này. Nó cũng có thể ngắn hơn để chia chương trình thành nhiều giai đoạn, nhưng thách thức ở đâu? ;)

Giải trình

Giải pháp này sử dụng rất nhiều các nhóm cân bằng của .NET. Để được giải thích đầy đủ, hãy xem bài đăng của tôi trên Stack Overflow , nhưng ý chính là các nhóm bắt trong .NET là các ngăn xếp, trong đó mỗi lần chụp mới đẩy một chuỗi con khác và ở đó cũng có thể bật lại từ ngăn xếp đó. Điều này cho phép bạn đếm số lượng khác nhau trong một chuỗi. Trong trường hợp này, nó cho phép chúng tôi thực hiện ba thanh trực tiếp dưới dạng ba nhóm chụp khác nhau trong đó mỗi đĩa được thể hiện bằng một bản chụp.

Để di chuyển các đĩa xung quanh giữa các thanh, chúng tôi sử dụng một (?<A-B>...)cú pháp lạ của cú pháp. Thông thường, điều này xuất hiện một bản chụp từ ngăn xếp Bvà đẩy lên ngăn xếp Achuỗi giữa bản thu thập được bật lên và phần đầu của nhóm này. Vì vậy, (?<A>a).(?<B-A>c)kết hợp với abcsẽ để Atrống và Bvới b(trái ngược với c). Tuy nhiên, do các giao diện có chiều dài thay đổi .NET có thể cho phép chụp (?<A>...)(?<B-A>...)chồng lấp . Vì lý do nào, nếu đó là trường hợp, giao điểm của hai nhóm được đẩy lên B. Tôi đã trình bày chi tiết hành vi này trong "phần nâng cao" về các nhóm cân bằng trong câu trả lời này .

Vào regex. Thanh A, BCtương ứng với các nhóm 3, 45trong regex. Hãy bắt đầu bằng cách khởi tạo thanh 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)+
)

Vì vậy, ví dụ nếu đầu vào kết thúc bằng 111, thì nhóm 3 / thanh Abây giờ sẽ giữ danh sách các ảnh chụp [111, 11, 1](phần trên cùng bên phải).

Bit tiếp theo của mã có cấu trúc sau:

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

Mỗi lần lặp của vòng lặp này xử lý một lệnh. Sự xen kẽ đầu tiên kéo một đĩa từ thanh đã cho (vào một nhóm tạm thời), lần xen kẽ thứ hai đặt đĩa đó lên thanh khác đã cho. Chúng ta sẽ thấy ngay lúc này cách thức hoạt động và cách chúng tôi đảm bảo rằng di chuyển là hợp lệ.

Đầu tiên, lấy một đĩa ra khỏi thanh nguồn:

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

Điều này sử dụng hành vi giao nhau nhóm kỳ lạ mà tôi đã mô tả ở trên. Lưu ý nhóm đó 3, 45sẽ luôn luôn giữ chuỗi con của 1s ở phần cuối của chuỗi có tương ứng với kích thước của đĩa dài. Bây giờ chúng ta sử dụng (?<1-N>.+)để bật đĩa trên cùng ra khỏi ngăn xếp Nvà đẩy giao điểm của chuỗi con này với trận đấu .+lên ngăn xếp 1. Vì .+luôn luôn bao gồm toàn bộ bản chụp bật ra N, chúng tôi biết rằng điều này chỉ đơn giản là di chuyển bản chụp.

Tiếp theo, chúng tôi đặt đĩa này từ ngăn xếp 1lên ngăn xếp tương ứng với thanh thứ hai:

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

Lưu ý rằng chúng tôi không phải dọn dẹp ngăn xếp 1, chúng tôi có thể để đĩa ở đó, vì chúng tôi sẽ đặt một cái mới lên trên trước khi sử dụng lại ngăn xếp. Điều đó có nghĩa là chúng ta có thể tránh (?<A-B>...)cú pháp và chỉ cần sao chép chuỗi qua (\1). Để đảm bảo rằng di chuyển là hợp lệ, chúng tôi sử dụng giao diện tiêu cực (?!\N). Điều này đảm bảo rằng, từ vị trí chúng tôi muốn khớp với đĩa hiện tại, không thể khớp với đĩa đã có trên ngăn xếp N. Điều này chỉ có thể xảy ra nếu a) \Nsẽ không bao giờ khớp vì ngăn xếp hoàn toàn trống hoặc b) the disc on top of stackN is larger than the one we're trying to match with\ 1`.

Cuối cùng, tất cả những gì còn lại là đảm bảo rằng a) chúng tôi khớp với tất cả các hướng dẫn và b) thanh ABtrống, để tất cả các đĩa được chuyển lên C.

(?!\3|\4)1

Chúng tôi chỉ đơn giản kiểm tra xem cả hai đều \3không \4khớp (chỉ là trường hợp nếu cả hai đều trống, bởi vì bất kỳ đĩa thực tế nào cũng khớp) và sau đó chúng tôi có thể khớp với nhau 1để chúng tôi không bỏ qua bất kỳ hướng dẫn nào.


14

Java "chỉ" 311 272 263 261 260 259 256 byte

Đã lưu 39 vô số byte do @Frozn nhận thấy một tính năng gỡ lỗi cũ cũng như một số thủ thuật đánh golf thông minh.

Phiên bản chơi gôn

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;}

vô duyên với lời giải thích và ngăn xếp in đẹp ở mỗi bước

/*
 * 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!");
    }

}

Phiên bản không có bản quyền có một tính năng trong đó nó sẽ in ra các ngăn xếp trông như thế nào ở mỗi bước như vậy ...

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

Không gì System.out.println(Arrays.toString(s))làm gì?
Frozn

Nó sẽ in đẹp các ngăn xếp. Giống như vậy [[2,1,0], [] []]
Rohan Jhunjhunwala

Rất tiếc @Frozn là một tính năng gỡ lỗi hiện đang xóa
Rohan Jhunjhunwala

Tôi biết, chỉ tự hỏi tại sao nó ở đó :) Bạn cũng có thể thay thế &&bằng &.
Frozn

@Frozn Tôi không thể thay thế điều đó một cách đáng buồn vì tôi đã dựa vào hành vi ngắn mạch để tránh cố gắng nhìn trộm vào một ngăn xếp trống. Cảm ơn vì đã giảm 39 byte
Rohan Jhunjhunwala

9

Python 2, 186 167 158 135 127 115 110 102 byte

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]:_

Đưa đầu vào vào STDIN theo định dạng sau:

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

Đó là, một bộ dữ liệu Python về số lượng đĩa và danh sách các bộ dữ liệu Python (from_rod,to_rod). Như trong Python, các dấu ngoặc đơn xung quanh là tùy chọn. Thanh không có chỉ số.

Ví dụ: trường hợp thử nghiệm này:

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

sẽ được đưa ra như:

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

Nếu giải pháp hợp lệ, không có kết quả gì và thoát ra với mã thoát là 0. Nếu không hợp lệ, hãy ném ngoại lệ và thoát với mã thoát là 1. Ném một IndexErrornếu không di chuyển đến một thanh không tồn tại hoặc cố gắng lấy đĩa ra thanh không có đĩa trên đó, ZeroDivisionErrornếu đĩa được đặt trên đỉnh của đĩa nhỏ hơn hoặc NameErrornếu có đĩa còn lại trên thanh thứ nhất hoặc thứ hai ở cuối.

Đã lưu 13 byte nhờ @KarlKastor!

Đã lưu 8 byte nhờ @xnor!


1
Việc kiểm tra mỗi cọc được sắp xếp có vẻ quá phức tạp. Bạn có thể kiểm tra xem đĩa di chuyển có lớn hơn đĩa trên cùng của cọc không?
xnor

@xnor Cảm ơn, nên làm việc. Thêm nó ngay bây giờ.
Đồng

5

Python 2.7, 173 158 138 130 127 123 byte:

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)

Đưa đầu vào thông qua stdin ở định dạng các (<Number of Discs>,<Moves>)nơi <Moves>được cho là một mảng chứa các bộ tương ứng với mỗi di chuyển, mỗi bảng chứa một cặp dấu phẩy tách ra số nguyên. Ví dụ, trường hợp thử nghiệm:

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

đưa ra trong bài sẽ được đưa ra là:

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

đến chương trình của tôi. Xuất ra IndexErrornếu điều kiện thứ 3 không được đáp ứng, NameErrornếu điều kiện thứ 2 không được đáp ứng và Falsenếu điều kiện thứ 1 không được đáp ứng. Nếu không thì đầu ra True.


hai điều: biến Ykhông bao giờ được xác định trong mã của bạn (tôi nghĩ đó phải là J) và U[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]ngắn hơn 3 ký tựstmt1 if cond else stmt2
jermenkoo

@jermenkoo Chà, tôi sử dụng Ybiến đó như thế là để nâng cao NameErrorbất cứ khi nào điều kiện thứ 2 không được đáp ứng. Nếu tôi được thay đổi Yđể J, thì NameErrorsẽ không được nâng lên. Vì lý do này, tôi cũng không thể làm được U[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]vì điều này sẽ tăng lên NameError mọi lúc , không chỉ khi điều kiện thứ 2 không được đáp ứng.
R. Kap

được rồi, cảm ơn lời giải thích của bạn
jermenkoo

5

VBA, 234 217 213 196 byte

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

Định dạng đầu vào cho di chuyển là một chuỗi có số chữ số chẵn (012). Yêu cầu có trong bảng tính, = H ([số lượng đĩa], [chuỗi di chuyển])

Mảng A giữ vị trí thanh của các đĩa khác nhau. Việc di chuyển chỉ đơn giản là cập nhật lần xuất hiện đầu tiên của số que "Từ" thành số que "Đến". Nếu trước tiên bạn gặp đĩa que "Tới" hoặc không có đĩa que "Từ" thì đó là một động thái không hợp lệ. Tổng "giá trị thanh" của A được giữ bằng L, cần kết thúc ở mức 2N. Lỗi được tích lũy dưới dạng số âm trong E.

Tương tự như các giải pháp khác, việc "di chuyển" một đĩa từ tháp này sang tháp khác không bị cấm. Tôi có thể cấm nó thêm 6 byte.

Các kết quả

Kết quả chức năng trong cột đầu tiên (trường hợp n = 3 cuối cùng là sự bổ sung của tôi bằng cách sử dụng một thanh phụ).

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 byte

<?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;

Tập lệnh dòng lệnh, lấy đầu vào là chiều cao sau đó một loạt các chỉ mục mảng (0 được lập chỉ mục), ví dụ 1 0 2 hoặc 2 0 1 0 2 1 2 cho các trường hợp thử nghiệm ngắn nhất chiều cao 1 hoặc 2.
Echos 1 về trường hợp thật và không có gì trên những trường hợp sai.
Đưa ra 2 thông báo và 1 cảnh báo vì vậy cần phải được chạy trong một môi trường làm im lặng những người đó.


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]

Định dạng đầu vào: hàm có 2 đối số

  • arg 1, số, số vòng
  • arg 2, mảng chuỗi, mỗi chuỗi 2 ký tự '0', '1', '2'

Đầu ra: trả về 1 nếu ok, 0 nếu không hợp lệ, ngoại lệ nếu thanh không tồn tại

Ít chơi gôn và giải thích

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
)

Lưu ý kiểm tra : hàng đầu tiên của chức năng Kiểm tra là cần thiết để chuyển đổi định dạng đầu vào được đưa ra trong câu hỏi sang đầu vào mà chức năng của tôi mong đợi

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>

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.