Zamiana numerów [zamknięte]

10

To powszechna łamigłówka, którą wielu z was rozwiązało ręcznie. Teraz nadszedł czas, aby napisać algorytm, aby rozwiązać to samo.

Są równe liczby drążków dopasowanych ustawionych w dwóch różnych bokach naprzeciwko siebie. Między nimi jest jedna pusta przestrzeń. Powiedz coś takiego jak na poniższym rysunku (jeśli całkowita liczba pasujących kijów wynosi 4).

wprowadź opis zdjęcia tutaj

Każdy kij może przesunąć się o jeden krok w kierunku do przodu (jeśli bezpośrednia przednia przestrzeń jest wolna), lub można go przeskoczyć nad jednym kijem z przodu i wylądować w wolnej przestrzeni (jeśli ta przestrzeń jest wolna). Ruch w odwrotnym kierunku nie jest możliwy (nawet przestrzeń jest wolna). Niedozwolony jest również skok do tyłu. Tylko jeden ruch jest dozwolony w jednym kroku.

Teraz musisz napisać algorytm, aby znaleźć minimalne wymagane kroki, za pomocą których wszystkie drążki zapałek po lewej stronie wylądują po prawej stronie, a wszystkie drążki zapałek po prawej stronie wylądują po lewej stronie.

Na przykład: jeśli w sumie są 2 kijki do zapałek (po 1 z każdej strony), kroki będą następujące:

wprowadź opis zdjęcia tutaj

Uwaga: na powyższym rysunku najpierw przesunięto lewy drążek boczny. Inne rozwiązanie istnieje, gdy prawy drążek boczny porusza się pierwszy. Ale w przypadku tego problemu musisz podać tylko jedno rozwiązanie, przy założeniu, że lewy drążek porusza się pierwszy.

Poniższy rysunek opisuje ruchy za pomocą 4 kijów zapałek (2 z każdej strony):

wprowadź opis zdjęcia tutaj

Uwaga: na powyższym rysunku najpierw przesunięto lewy drążek boczny. Inne rozwiązanie istnieje, gdy prawy drążek boczny porusza się pierwszy. Ale w przypadku tego problemu musisz podać tylko jedno rozwiązanie, przy założeniu, że lewy drążek porusza się pierwszy.

[Założenie: Wejście może być dowolną liczbą parzystą od 02 do 14 (tj. 1 do 7 pasujących kijów z każdej strony). W przypadku danych wejściowych poza tym zakresem nie ma potrzeby sprawdzania poprawności ani podawania komunikatu o błędzie. Uwaga: W wyniku każdy krok jest oddzielony znakiem „|” (rura) znak. Programiści COBOL powinni zawsze przyjmować PIC 9 (2) jako wielkość wejściową i mogą również zakładać, że wyjście ma być ustalone maksymalnej długości 450 znaków, wypełnione spacjami po prawej stronie.]


Przykładowe dane wejściowe:

02  

Przykładowe dane wyjściowe:

01To02|03To01|02To03|


Przykładowe dane wejściowe:

04  

Przykładowe dane wyjściowe:

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


Przykładowe dane wejściowe:

06  

Przykładowe dane wyjściowe:

03To04|05To03|06To05|04To06|02To04|01To02|03To01|05To03|07To05|06To07|04To06|02To04|03To02|05To03|04To05|
użytkownik2076421
źródło
Jeśli nie możesz dołączyć obrazów bezpośrednio, czy możesz podać linki, aby umożliwić innym osobom ich edycję?
Peter Taylor
2
Zrobiłem kilka szybkich zdjęć. Mam nadzieję, że są zgodne z intencjami autora.
primo
3
Warunek do zwycięstwa?
Shmiddty,

Odpowiedzi:

3

APL 129

Poniższy kod przenosi dane wejściowe i wyjściowe na ekran w określonym formacie:

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)),¨⊂'|')~' '

Spora część kodu zajmuje formatowanie wyniku. Uzupełnieniem logiki jest pojawienie się symbolu ⋄ w kodzie.

Poniżej znajduje się wynik dla wpisu 08 jako kontroli:

04To05|06To04|07To06|05To07|03To05|02To03|04To02|06To04|08To06|09To08|07To09|05To07|03To05|01To03|02To01|04To02|06To04|08To06|07To08|05To07|03To05|04To03|06To04|05To06|
Graham
źródło
1
Zawsze czuję, że APL oszukuje>. <
Shmiddty
@Shmiddty Obawiam się, że każdy język oparty wyłącznie na symbolach, taki jak APL, J, GolfScript itp., Najprawdopodobniej wygra golfa w golfa przeciwko bardziej pełnym językom;)
Graham
3

JavaScript 178 174 161

promptza nto alertodpowiedź s. (Bez 0wyściółki)

Najnowszy:

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)

Wykorzystuje to koncepcję, że wzorzec jest dublowany:

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

A zatem n=2wzór ruchu jest następujący:

rLr
mjm

Co równa się

+1 -2 +1

Ten wzór powtarza się tak ( 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

Widzimy tutaj kilka wzorów:

  1. Ruch zmienia się między lewą a prawą
  2. Liczba ruchów w danym kierunku wzrasta od 1 do n/2, który powtarza się 3 razy, a następnie zmniejsza z powrotem do 1.
  3. Rodzaj ruchu zmienia się na przemian między przesuwaniem i skakaniem, liczba zmian w rzędzie jest stała 1, a liczba skoków sekwencyjnych rośnie od 1, n/2a następnie maleje z powrotem do 1.
  4. Podsumowanie ruchów wynosi zawsze 0. (Nie jestem pewien, czy jest to rzeczywiście istotne)

n=14:

rLlRRrLLLlRRRRrLLLLLlRRRRRRrLLLLLLLrRRRRRRlLLLLLrRRRRlLLLrRRlLr
mjmjjmjjjmjjjjmjjjjjmjjjjjjmjjjjjjjmjjjjjjmjjjjjmjjjjmjjjmjjmjm

Przykładowe dane wyjściowe:

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|

Oto pseudo kod do zademonstrowania metody:

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
  }
}
Shmiddty
źródło
2
Masz rację, że wzór jest bardziej wyraźny przy pomocy l/L/r/Ri m/j. Podoba mi się pomysł oddzielenia odległości od kierunku
Gordon Bailey
2

C - 216 213

Moje rozwiązanie opiera się na dwóch faktach:

  1. Pole „do” to pole „z” poprzedniego ruchu (ponieważ zawsze tworzysz puste miejsce w miejscu, z którego się poruszasz, i zawsze przechodzisz do pustego miejsca)

  2. Przesuwane odległości i kierunki są bardzo regularne. Dla pierwszych 3 przypadków testowych są to:

    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

Mając to na uwadze, po prostu napisałem program do tworzenia i kontynuowania tego wzoru. Jestem prawie pewien, że musi istnieć naprawdę piękny i znacznie bardziej elegancki rekurencyjny sposób na napisanie tego, ale jeszcze tego nie rozgryzłem:

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

I grał w golfa (chociaż było to wyzwanie kodowe, a nie golfowe):

#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}}
Gordon Bailey
źródło
Kiedy uruchamiam twoją wersję golfa, dostaję awarię.
artistoex
Och, przepraszam, zapomniałem wspomnieć, że dane wejściowe podano jako argument wiersza poleceń - jeśli uruchomisz je bez argumentów, segfault. Ale właściwie teraz, kiedy o tym wspominasz, nie wiem, dlaczego myślałem, że argumenty wiersza poleceń będą krótsze niż scanf. Aktualizuję swoją odpowiedź lepszą wersją.
Gordon Bailey,
Wzór jest bardziej zauważalne podczas korzystania L / R / L / R (wielki człowiek "skok") N(2)=rLr, N(4)=rLlRRlLr, N(6)=rLlRRrLLLrRRlLr, itd.
Shmiddty
2

Matematyka

To podejście buduje Nestedytowaną sekwencję wielkości i kierunku ruchów, sformatowaną jako {fromPosition,toPosition}, zaczynając od pozycji n, gdzie nodnosi się do liczby par dopasowania. Następnie Foldjest sekwencją w funkcję rozpoczynającą się od ruchu {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}}


Wizualizacja zamiany

r,, bi osą odpowiednio obrazami lub czerwonym dopasowaniem, niebieskim dopasowaniem i brakiem dopasowania.

mecze

Poniżej sformatowano dane wyjściowe z, zaby wyświetlić zamiany z dopasowaniami.

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]

swapstworzy listę stanów przy użyciu uporządkowanych par zpoleceń as, aby permutować listę początkową i kolejne.

swaps[1]

swapy 1

swapMatches wyświetla stany w siatce.

swapMatches[2]

zamiana2

swapMatches[3]

swapy3

DavidC
źródło
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
}

Znaki liczone za pomocą grep =|tr -d \ |wc -c

artistoex
źródło
1
Witaj w codegolf! Myślę, że zauważysz, że twoje rozwiązanie nie generuje poprawnych danych wyjściowych dla żadnego z przypadków testowych ( jsfiddle.net/SJwaU ). Dla danych wejściowych 02wartości są prawidłowe, ale brakuje w nim końcowego |. W pozostałych dwóch przypadkach wartości są dalekie, a formatowanie 10również jest nieprawidłowe. Nie jestem również pewien swojej metody liczenia postaci. Dlaczego liczysz tylko ciało funkcji minus zwrot?
Gordon Bailey,
@ Gordon Ups, wygląda na to, że popełniłem błąd w mojej ostatniej optymalizacji. Dzięki za wskazanie. Liczę ciało tylko dlatego, że na REPL to wszystko, czego potrzebujesz. Dekorację funkcji umieściłem tylko dla wygody.
artistoex,
Musisz doliczyć odpowiednie białe znaki (np. Znaki nowej linii) do swojej sumy.
Shmiddty,
@shmiddty tr -d \ |wc -cbierze pod uwagę nowe linie
artistoex