Trao đổi số [đóng]


10

Đây là một câu đố phổ biến nhiều bạn đã giải quyết bằng tay. Bây giờ đây là thời gian để viết một thuật toán để giải quyết tương tự.

Có những que diêm số bằng nhau xếp thành hai bên khác nhau đối diện với hướng của nhau. Có một khoảng trống duy nhất giữa chúng. Nói một cái gì đó giống như hình dưới đây (nếu tổng số que diêm là 4).

nhập mô tả hình ảnh ở đây

Mỗi cây gậy có thể trượt một bước theo hướng về phía trước (nếu không gian phía trước ngay lập tức) hoặc nó có thể nhảy qua một cây gậy ở phía trước và rơi vào không gian trống (nếu không gian đó là miễn phí). Việc di chuyển theo hướng ngược lại là không thể (thậm chí không gian là miễn phí). Không nhảy ngược cũng được cho phép. Chỉ một động thái được cho phép trong một bước.

Bây giờ, bạn phải viết một thuật toán để tìm các bước tối thiểu cần thiết bằng cách sử dụng tất cả các que diêm bên tay trái sẽ hạ cánh ở phía bên tay phải và tất cả các que diêm bên phải sẽ hạ cánh ở phía bên tay trái.

Ví dụ: Nếu có tổng số 2 que diêm (mỗi bên 1 cái) thì các bước sẽ là:

nhập mô tả hình ảnh ở đây

Lưu ý: Trong hình trên, thanh bên trái được di chuyển trước. Một giải pháp khác tồn tại khi thanh bên phải di chuyển đầu tiên. Nhưng đối với vấn đề này, bạn phải đưa ra một giải pháp duy nhất và đó cũng là giả định rằng thanh bên trái di chuyển trước.

Hình dưới đây mô tả các bước di chuyển với 4 que diêm (mỗi bên 2 cái):

nhập mô tả hình ảnh ở đây

Lưu ý: Trong hình trên, thanh bên trái được di chuyển trước. Một giải pháp khác tồn tại khi thanh bên phải di chuyển đầu tiên. Nhưng đối với vấn đề này, bạn phải đưa ra một giải pháp duy nhất và đó cũng là giả định rằng thanh bên trái di chuyển trước.

[Giả định: Đầu vào có thể là bất kỳ số chẵn nào trong khoảng từ 02 đến 14 (tức là 1 đến 7 que diêm ở mỗi bên). Đối với các đầu vào ngoài phạm vi này, bạn không cần thực hiện bất kỳ xác nhận nào, cũng không cần cung cấp bất kỳ thông báo lỗi nào. Lưu ý: Trong đầu ra, mỗi bước được phân tách bằng dấu '|' (ống) ký tự. Các lập trình viên của COBOL phải luôn coi PIC 9 (2) là kích thước đầu vào & cũng có thể giả sử đầu ra có độ dài tối đa 450 ký tự, được đệm bằng khoảng trắng ở bên phải.]


Đầu vào mẫu:

02  

Đầu ra mẫu:

01To02|03To01|02To03|


Đầu vào mẫu:

04  

Đầu ra mẫu:

02To03|04To02|05To04|03To05|01To03|02To01|04To02|03To04|


Đầu vào mẫu:

06  

Đầu ra mẫu:

03To04|05To03|06To05|04To06|02To04|01To02|03To01|05To03|07To05|06To07|04To06|02To04|03To02|05To03|04To05|

Nếu bạn không thể bao gồm các hình ảnh trực tiếp, bạn có thể cung cấp liên kết cho người khác để chỉnh sửa chúng không?
Peter Taylor

2
Tôi đã thực hiện một số hình ảnh nhanh chóng. Hy vọng rằng chúng phù hợp với ý định của tác giả ban đầu.
primo 16/2/13

3
Điều kiện để chiến thắng?
Shmiddty

Câu trả lời:


3

APL 129

Mã dưới đây đưa đầu vào màn hình và đầu ra ra màn hình theo định dạng được chỉ định:

n←n,n++\1↓z←(⌽z),((¯1*~2|n)×n⍴2),z←⌽∊(¯1*2|⍳n)ר1,((⍳(n←.5×⍎⍞)-1)⍴¨2),¨1⋄(∊(((¯2↑¨'0',¨⍕¨n),¨⊂'To'),¨(¯2↑¨'0',¨⍕¨n-z)),¨⊂'|')~' '

Một phần ba tốt của mã được đưa lên định dạng đầu ra. Logic được hoàn thành bởi sự xuất hiện của ký hiệu in trong mã.

Dưới đây là kết quả cho đầu vào 08 dưới dạng kiểm tra:

04To05|06To04|07To06|05To07|03To05|02To03|04To02|06To04|08To06|09To08|07To09|05To07|03To05|01To03|02To01|04To02|06To04|08To06|07To08|05To07|03To05|04To03|06To04|05To06|

1
Tôi luôn cảm thấy như APL đang lừa dối>. <
Shmiddty

@Shmiddty Tôi e rằng bất kỳ ngôn ngữ hoàn toàn dựa trên biểu tượng nào như APL, J, GolfScript, v.v ... rất có thể sẽ giành được mã golf trước các ngôn ngữ dựa trên từ dài hơn;)
Graham

3

Javascript 178 174 161

prompts cho nrồi alerts trả lời. (Không có 0đệm)

Muộn nhất:

t=1+(m=prompt(s=i='')/2);for(z=Math.abs;i++<m*2;)for(j=m-z(m-i),s+=(t+=a=(m%2^z(m+.5-i)%2-.5)*-2+1)+'To'+(t-a)+'|';j--;)s+=(t+=a=i%2*4-2)+'To'+(t-a)+'|';alert(s)

2:

z=Math.abs;t=m=prompt(o=[])/2;t++;for(s=i='';i++<m*2;)for(j=m-z(m-i),o.push((z(m+.5-i)%2-.5)?-1:1);j--;)o.push(i%2?2:-2);o.map(function(a){s+=(t+=a)+'To'+(t-a)+'|'});alert(s)

1:

t=m=prompt(o=[])/2+1;for(s=i='';++i<m;)for(j=i,o.push(i%2?-1:1);j--;)o.push(i%2?2:-2);o.concat(o.slice().reverse().slice(m-1)).map(function(a){s+=(t+=a)+'To'+(t-a)+'|'});alert(s)

Điều này sử dụng khái niệm rằng mô hình được nhân đôi:

Key
R='Jump Right'
r='Shift Right'
L='Jump Left'
l='Shift Left'
m='Move'
j='Jump'

Vì vậy, ở đâu n=2, mô hình của phong trào là:

rLr
mjm

Mà tương đương với

+1 -2 +1

Mẫu này lặp lại như vậy ( n=8)

rLlRRrLLLlRRRRlLLLrRRlLr
mjmjjmjjjmjjjjmjjjmjjmjm
+1 -2 -1 +2 +2 +1 -2 -2 -2 -1 +2 +2 +2 +2 -1 -2 -2 -2 +1 +2 +2 -1 -2 +1

Chúng ta có thể nhận thấy một vài mẫu ở đây:

  1. Chuyển động xen kẽ giữa trái và phải
  2. Số lượng chuyển động theo một hướng cụ thể tăng từ 1 đến n/2, lặp lại 3 lần, sau đó giảm xuống 1.
  3. Loại chuyển động xen kẽ giữa dịch chuyển và nhảy, số lượng ca liên tiếp là một hằng số 1và số lần nhảy liên tiếp tăng từ 1 đến n/2sau đó giảm dần xuống 1.
  4. Tổng các chuyển động luôn là 0. (Không chắc điều này có thực sự phù hợp không)

n=14:

rLlRRrLLLlRRRRrLLLLLlRRRRRRrLLLLLLLrRRRRRRlLLLLLrRRRRlLLLrRRlLr
mjmjjmjjjmjjjjmjjjjjmjjjjjjmjjjjjjjmjjjjjjmjjjjjmjjjjmjjjmjjmjm

Đầu ra mẫu:

f(2):

1To2|3To1|2To3| 

f(8):

4To5|6To4|7To6|5To7|3To5|2To3|4To2|6To4|8To6|9To8|7To9|5To7|3To5|1To3|2To1|4To2|6To4|8To6|7To8|5To7|3To5|4To3|6To4|5To6|

f(40):

20To21|22To20|23To22|21To23|19To21|18To19|20To18|22To20|24To22|25To24|23To25|21To23|19To21|17To19|16To17|18To16|20To18|22To20|24To22|26To24|27To26|25To27|23To25|21To23|19To21|17To19|15To17|14To15|16To14|18To16|20To18|22To20|24To22|26To24|28To26|29To28|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|12To13|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|31To30|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|10To11|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|33To32|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|8To9|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|35To34|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|6To7|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|37To36|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|4To5|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|39To38|37To39|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|3To5|2To3|4To2|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|40To38|41To40|39To41|37To39|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|3To5|1To3|2To1|4To2|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|40To38|39To40|37To39|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|3To5|4To3|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|37To38|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|6To5|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|35To36|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|8To7|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|33To34|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|10To9|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|31To32|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|12To11|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|29To30|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|14To13|16To14|18To16|20To18|22To20|24To22|26To24|28To26|27To28|25To27|23To25|21To23|19To21|17To19|15To17|16To15|18To16|20To18|22To20|24To22|26To24|25To26|23To25|21To23|19To21|17To19|18To17|20To18|22To20|24To22|23To24|21To23|19To21|20To19|22To20|21To22|

Đây là một số mã giả để trình bày phương pháp:

var mid=cursor=N/2,delta
cursor++                 // the cursor is where the empty space is.
for(i=0; i++<N;){
  delta = (mid%2^abs(mid+.5-i)%2-.5)*-2+1;  // 1 or -1
  print((cursor+delta) + 'To' + cursor + '|')
  cursor+=delta
  for(j=mid-abs(mid-i);j--;)
  {
    delta = i%2*4-2  // 2 or -2
    print((cursor+delta) + 'To' + cursor + '|')
    cursor+=delta
  }
}

2
Bạn đúng rằng mô hình rõ ràng hơn với l/L/r/Rm/j. Tôi thích ý tưởng phân tách khoảng cách di chuyển từ hướng
Gordon Bailey

2

C - 216 213

Giải pháp của tôi dựa trên hai sự thật:

  1. Trường "đến" là trường "từ" của lần di chuyển trước (vì bạn luôn tạo một vị trí trống trong không gian bạn di chuyển và ou luôn di chuyển đến một vị trí trống)

  2. Có một mô hình rất đều đặn cho khoảng cách và hướng được di chuyển. Đối với 3 trường hợp thử nghiệm đầu tiên, chúng là:

    1 -2 1

    1 -2 -1 2 2 -1 -2 1

    1 -2 -1 2 2 1 -2 -2 -2 1 2 2 -1 -2 1

Với ý nghĩ đó, về cơ bản tôi chỉ viết một chương trình để sản xuất và tiếp tục mô hình đó. Tôi khá chắc chắn rằng phải có một cách đệ quy thực sự đẹp và thanh lịch hơn nhiều để viết điều này, nhưng tôi chưa tìm ra nó:

#include <stdio.h>

int main(int argc, const char *argv[])
{
   int upper_bound = atoi(argv[1]) / 2;
   int len;
   int from;
   int to = upper_bound + 1;
   int direction = 1;
   int i;

   for(len = 1; len <= upper_bound; ++len){
      for(i = len-1; i >=0; --i){
         from = to - direction*(1 + (i!=0));
         printf("%02dTo%02d|",from,to);
         to = from;
      }
      direction*=-1;
   }
   for(i=1; i < len; ++i){
      from = to - direction*2;
      printf("%02dTo%02d|",from,to);
      to = from;
   }
   direction*=-1;
   for(--len; len >= 0; --len){
      for(i = 0; i < len; ++i){
         from = to - direction*(1 + (i!=0));
         printf("%02dTo%02d|",from,to);
         to = from;
      }
      direction*=-1;
   }
   return 0;
}

Và chơi gôn (mặc dù đây là một thử thách mã chứ không phải golf):

#define B {F=T-D*(1+(i!=0));printf("%02dTo%02d|",F,T);T=F;}D*=-1;
L,F,T,D,i;main(int U,char**A){U=atoi(A[1])/2;T=U+1;D=1;for(L=1;L<=U;++L){for(i=L-1;i>=0;--i)B}for(i=1;i<L;++i)B for(--L;L>=0;--L){for(i=0;i<L;++i)B}}

#define B {F=T-D*(1+(i!=0));printf("%02dTo%02d|",F,T);T=F;}D*=-1;
L,F,T,D,i;main(int U){scanf("%d",&U);U/=2;T=U+1;D=1;for(L=1;L<=U;++L){for(i=L-1;i>=0;--i)B}for(i=1;i<L;++i)B for(--L;L>=0;--L){for(i=0;i<L;++i)B}}

Khi tôi chạy phiên bản chơi gôn của bạn, tôi nhận được một segfault.
artistoex 17/2/13

Ôi xin lỗi, tôi đã quên đề cập rằng đầu vào được đưa ra dưới dạng đối số dòng lệnh - nếu bạn chạy nó mà không có đối số thì nó sẽ segfault. Nhưng thực sự bây giờ khi bạn đề cập đến nó, tôi không biết tại sao tôi nghĩ các đối số dòng lệnh sẽ ngắn hơn scanf. Tôi đang cập nhật câu trả lời của tôi với một phiên bản tốt hơn.
Gordon Bailey

Mô hình là đáng chú ý hơn khi bạn sử dụng L / R / l / r (lớn con người "nhảy"): N(2)=rLr, N(4)=rLlRRlLr, N(6)=rLlRRrLLLrRRlLrvv
Shmiddty

2

Toán học

Cách tiếp cận này xây dựng một Nestchuỗi ed về kích thước và hướng di chuyển, được định dạng là {fromPosition,toPosition}, bắt đầu bằng vị trí n, trong đó nđề cập đến số lượng các cặp khớp. Sau đó, Foldnó là chuỗi thành một chức năng bắt đầu bằng di chuyển {n, n+1}.

z@n_:=(p=1;h@t_:=Append[{Table[2 (-1)^t,{t}]},{(-1)^(t+1)}];
k=Join[Reverse@Drop[#,n],#]&[Flatten@Nest[Prepend[#,h[p++]]&,{},n]];
Fold[Append[#,{#[[-1,1]]-#2,#[[-1,1]]}]&,{{n,n+k[[1]]}},Rest@k])

z[1]

{{1, 2}, {3, 1}, {2, 3}}


z[4]

{{4, 5}, {6, 4}, {7, 6}, {5, 7}, {3, 5}, {2, 3}, {4, 2}, {6, 4}, { 8, 6}, {9, 8}, {7, 9}, {5, 7}, {3, 5}, {1, 3}, {2, 1}, {4, 2}, {6, 4}, {8, 6}, {7, 8}, {5, 7}, {3, 5}, {4, 3}, {6, 4}, {5, 6}}


z[7]

{{7, 8}, {9, 7}, {10, 9}, {8, 10}, {6, 8}, {5, 6}, {7, 5}, {9, 7}, { 11, 9}, {12, 11}, {10,12}, {8, 10}, {6, 8}, {4, 6}, {3, 4}, {5, 3}, {7, 5}, {9, 7}, {11, 9}, {13, 11}, {14, 13}, {12, 14}, {10, 12}, {8, 10}, {6, 8} , {4, 6}, {2, 4}, {1, 2}, {3, 1}, {5, 3}, {7, 5}, {9, 7}, {11, 9}, { 13, 11}, {15, 13}, {14, 15}, {12, 14}, {10, 12}, {8, 10}, {6, 8}, {4, 6}, {2, 4}, {3, 2}, {5, 3}, {7, 5}, {9, 7}, {11, 9}, {13, 11}, {12, 13}, {10, 12} , {8, 10}, {6, 8}, {4, 6}, {5, 4}, {7, 5}, {9, 7}, {11, 9}, {10, 11}, { 8, 10}, {6, 8}, {7, 6}, {9, 7}, {8, 9}}


Hình dung các hoán đổi

r, bolà hình ảnh hoặc một trận đấu màu đỏ, một trận đấu màu xanh lam và không có trận đấu tương ứng.

diêm

Các định dạng sau đây đầu ra từ zđể hiển thị các giao dịch hoán đổi với khớp.

swaps[n_]:=FoldList[Grid[{Permute[#[[1,1]],Cycles[{#2}]],Range[2n+1]}]&,
Grid[{Join[Table[r,{n}],{o},Table[b,{n}]],Range[2n+1]}],z[n]]

swapMatches[n_]:=Grid[Partition[swaps[n],2,2,1,""],Dividers->All]

swapstạo ra một danh sách các trạng thái bằng cách sử dụng các cặp lệnh theo thứ tự zđể hoán vị danh sách ban đầu và các danh sách tiếp theo.

swaps[1]

hoán đổi1

swapMatches hiển thị các trạng thái trong một lưới.

swapMatches[2]

hoán đổi2

swapMatches[3]

hoán đổi3


0

Javascript 191

function f(N) {
    n=N>>=i=c=a='1';n++
    s=z='0'
    for(k=b='34';i<N;k=i%2?a+=z+z:b+='44',i++)c=k+c
    t=''
    i=N*(N+1)/2
    l=2*i+N
    for(;l;n+=(i>=1?r=c[i-1]:i<=-N?c[-i-N]:k[1])-2,t+=(s=n>9?'':z)+n+a+'|',--l,--i)a='To'+s+n
    return t
}

Nhân vật được tính bằng grep =|tr -d \ |wc -c


1
Xin chào và chào mừng đến với codegolf! Tôi nghĩ rằng bạn sẽ thấy giải pháp của mình không tạo ra đầu ra chính xác cho bất kỳ trường hợp thử nghiệm nào ( jsfiddle.net/SJwaU ). Đối với đầu vào 02, các giá trị là chính xác, nhưng nó thiếu dấu |. Đối với hai trường hợp khác, các giá trị bị tắt và định dạng 10cũng sai. Cũng không chắc chắn về phương pháp đếm nhân vật của bạn. Tại sao bạn chỉ đếm cơ thể chức năng trừ đi sự trở lại?
Gordon Bailey

@gordon Rất tiếc, có vẻ như tôi đã mắc lỗi trong tối ưu hóa gần đây nhất của mình. Cảm ơn đã chỉ ra. Tôi chỉ đếm cơ thể vì trên REPL, đó là tất cả những gì bạn cần. Tôi đã đặt trang trí chức năng chỉ để thuận tiện.
artistoex

Bạn cần phải tính khoảng trắng có liên quan (ví dụ: dòng mới) trong tổng số của bạn.
Shmiddty

@shmiddty tr -d \ |wc -cđưa các dòng mới vào tài khoản
artistoex
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.