Narysuj ścieżkę permutacji

20

Wyobraź sobie następujące diagramy jako zestawy pionowych rur krzyżujących się.

1 2    1 2    1 2 3 4
\ /    \ /    \ / \ /
 X      |      |   |
/ \    / \    / \ / \
2 1    1 2   |   X   |
              \ / \ /
               X   X
              / \ / \
              3 1 4 2

Na schemacie najbardziej po lewej stronie 1i 2przesuwają się po swoich odpowiednich ukośnikach, krzyżują się Xi wychodzą po przeciwnych stronach od miejsca, w którym zaczęli.

To ten sam pomysł na środkowym schemacie, ale |oznacza, że ​​ścieżki się nie krzyżują, więc nic się nie zmienia.

Skrajnej prawej przedstawia schemat bardziej złożona rurka trasowania permutacji 1 2 3 4się 3 1 4 2.

Cel

Twoim celem w tym golfowym wyzwaniu golfowym jest narysowanie tych „schematów trasowania rur” z uwzględnieniem permutacji takiej jak 3 1 4 2. Zwycięży najkrótszy program w bajtach.

Detale

  1. Dane wejściowe pochodzą ze stdin jako dowolnej permutacji liczb od 1 do n oddzielonych spacjami, gdzie n jest dodatnią liczbą całkowitą. Możesz założyć, że wszystkie dane wejściowe są dobrze sformułowane.
  2. Wyjście ze schematu routingu przechodzi na standardowe wyjście.

    • „Upuszczenie” liczb od 1 do n w kolejności na górze schematu powinno spowodować, że permutacja wejściowa wyjdzie na dole. (Góra i dół to zawsze warstwy ukośników).
    • Schemat nie musi być optymalnie mały. Może to być tyle poziomów, ile to konieczne, o ile jest poprawne.
    • Schemat powinien zawierać tylko znaki \/ X|oraz znaki nowej linii (bez cyfr).
    • |należy zawsze używać na najbardziej oddalonych skrzyżowaniach, ponieważ używanie Xnie ma sensu.
    • Kilka początkowych lub końcowych spacji jest w porządku, pod warunkiem, że schemat jest poprawnie ułożony.

Przykłady

Dane wejściowe 3 1 4 2mogą produkować (tak samo jak powyżej)

 \ / \ /
  |   | 
 / \ / \
|   X   |
 \ / \ /
  X   X 
 / \ / \

Dane wejściowe 1mogą produkować

 \
  |
 /
|
 \
  |
 /

Dane wejściowe 3 2 1mogą produkować

 \ / \
  X   |
 / \ /
|   X
 \ / \
  X   |
 / \ /

Dane wejściowe 2 1 3 4 6 5mogą produkować

\ / \ / \ /
 X   |   X
/ \ / \ / \
Hobby Calvina
źródło
4
Świetne pytanie! Nie mogę uwierzyć, że dołączyłeś dopiero dwa tygodnie - wydajesz się być wszędzie.
xnor
@xnor: D Wielkie dzięki. Ale tak naprawdę spędziłem tu zbyt dużo czasu ...
Hobby Calvina
Czy można Xpołączyć się bezpośrednio |ze sposobem /? Do innego X?
xnor
1
@xnor Nie powinien on być zawsze w row of slashes, row of X's and |'s, row of slashes, row of X's and |'s, ... PDF.
Calvin's Hobbies
Może nbyć większy niż 10?
Οurous

Odpowiedzi:

4

Python 2, 218 219 220 222 224 227 243 247 252 259 261 264

l=map(int,raw_input().split())
f=n=len(l)
o=s=n*' \ /'
while f+n%2:
 f-=1;i=f+n&1;a=s[2*i:][:2*n]+'\n|   '[::2-i]
 while~i>-n:a+='|X'[l[i+1]<l[i]]+'   ';l[i:i+2]=sorted(l[i:i+2]);i+=2
 o=a+f%2*'|'+'\n'+o
print o[:-2*n]

Przyjąłem nieco inne podejście: znajduję wymiany potrzebne do sortowania danych wejściowych, a następnie odwracam je pionowo, aby uzyskać wymiany potrzebne do przekształcenia posortowanej listy w dane wejściowe. Jako dodatkowy bonus tego podejścia, może on przyjąć dowolną listę liczb i podać ścieżkę permutacji, aby zmienić rodzaj danych wejściowych na dane wejściowe.

Przykład:

$ python sort_path.py <<< '3 1 4 5 9 2 6 8 7'
 \ / \ / \ / \ / \
  |   |   |   |   |
 / \ / \ / \ / \ /
|   |   |   |   |   
 \ / \ / \ / \ / \
  |   |   |   |   |
 / \ / \ / \ / \ /
|   |   |   |   |   
 \ / \ / \ / \ / \
  |   |   |   |   |
 / \ / \ / \ / \ /
|   X   |   |   X   
 \ / \ / \ / \ / \
  |   X   |   X   |
 / \ / \ / \ / \ /
|   |   X   X   |   
 \ / \ / \ / \ / \
  X   |   X   |   |
 / \ / \ / \ / \ /
|   |   |   |   X   
 \ / \ / \ / \ / \

Ulepszenia:

264 -> 261: Przełączana zewnętrzna pętla od do do chwili.

261 -> 259: Używany f%2zamiast (c^m), ponieważ w pythonie operatory arytmetyczne mają wyższy priorytet niż operatory bitowe.

259 -> 252: Przełączana pętla wewnętrzna od do chwili. Połączone ii czmienne.

252 -> 247: Zmieniono kompilację, a następnie odwrócono, aby po prostu budować w odwrotnej kolejności.

247 -> 243: ręcznie dodawano nowe linie zamiast łączenia.

243 -> 227: Przyjęto metodę generowania linii cięcia przez grc (dzięki grc!) I dodano s.

227 -> 224: Przeniesiono generowanie linii ukośnika na wewnętrzną pętlę while, aby usunąć a %4i uratować postać za pomocą rozszerzonego krojenia.

224 -> 222: Usunięto m.

222 -> 220: f%2+n%2->f+n&1

220 -> 219: | 1<n-1|-> |~i>-n|(usunięto wiodące miejsce)

219 -> 218: Połączone inicjalizacje o oi si przeniesiony segment do końca.

isaacg
źródło
9

Python, 290

def g(o,u=1):
 s=['|']*o
 for i in range(o,n-1,2):v=r[i+1]in a[:a.index(r[i])]*u;s+=['|X'[v]];r[i:i+2]=r[i:i+2][::1-2*v]
 print'  '*(1-o)+'   '.join(s+['|']*(o^n%2))*u+'\n'*u+(' / \\'*n)[2*o:][:n*2]
a=map(int,raw_input().split())
n=len(a)
r=range(1,n+1)
o=1
g(1,0)
g(0)
while r!=a:g(o);o^=1

Postawiłem na dość podstawowe podejście, ale okazało się, że było trochę dłużej, niż się spodziewałem. Rozpatruje listę parami i decyduje, czy zamienić każdą parę. Jest to powtarzane dla każdego przecinającego się wiersza, dopóki lista nie pasuje do danych wejściowych.

Przykład:

$ python path.py
5 3 8 1 4 9 2 7 6
 \ / \ / \ / \ / \
  |   |   |   X   |
 / \ / \ / \ / \ /
|   X   X   X   X
 \ / \ / \ / \ / \
  X   X   X   X   |
 / \ / \ / \ / \ /
|   X   X   |   X
 \ / \ / \ / \ / \
  X   X   X   |   |
 / \ / \ / \ / \ /
|   |   |   X   |
 \ / \ / \ / \ / \
grc
źródło
2

HTML JavaScript, 553 419

Dziękuję @izlin i @TomHart za wskazanie moich błędów.

p=prompt();b=p.split(" "),l=b.length,d=l%2,o="",s=["","","\\/"],n="\n",a=[];for(i=0;i<l;i++){a[b[i]-1]=i+1;s[1]+=" "+s[2][i%2];s[0]+=" "+s[2][(i+1)%2];o+=" "+(i+1)}s[1]+=n,s[0]+=n;o+=n+s[1];f=1,g=2;do{var c="";for(var i=(f=f?0:1);i<l-1;i+=2)if(a[i]>a[i+1]){c+="  x ";g=2;t=a[i];a[i]=a[i+1];a[i+1]=t;}else c+="  | ";if(g==2){o+=(d?(f?"| "+c:c+"  |"):(f?"| "+c+"  |":c))+n;o+=(s[f]);}}while(--g);o+=" "+p;alert(o);

Przetestuj tutaj: http://goo.gl/NRsXEj
wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

JeffSB
źródło
Popełniłeś jeden mały błąd: pierwszy wiersz powinien być posortowanymi liczbami, a ostatni wiersz powinien być twoim wprowadzeniem, jak w powyższych przykładach.
izlin
Masz rację. Dzięki. Spojrzałem na wynik @ grc i pomyślałem, że liczby są pozycją początkową. Ups
JeffSB
Mogę patrzeć na to źle, ale na obu opublikowanych zdjęciach ostatni wiersz nie jest zbędny, ponieważ nic się nie zmienia?
TMH
Tak masz rację. Wiedziałem, że to konsensus co do tego, jak to zrobiłem. Ale prawdopodobnie nie musi tak być. Pomyślę o tym. Dziękuję za komentarz.
JeffSB
@izlin - Dziękujemy za zauważenie tego. Naprawiłem ten błąd.
JeffSB,
1

JavaScript - 395

378 jeśli nie wydrukuję liczb na wydruku, ale wygląda to znacznie lepiej i poprawia czytelność.
Sprawdź to tutaj . (z wersją bez

golfa ) wersja golfowa :

a=prompt(),n=a.split(" "),l=n.length,k=[],s="",i=1;for(j=0;j<l;j++){k[n[j]-1]=j+1;s+=" "+(j+1)}s+="\n";while(i++){for(j=0;j<l;j++)s+=i%2?j%2?" \\":" /":j%2?" /":" \\";for(z=0,y=0;z<l-1;z++)if(k[z]>k[z+1])y=1;if(y==0&&i!=2)break;s+="\n";for(m=i%2;m<l;m+=2){s+=i%2&&m==1?"|":"";if(k[m]>k[m+1]){[k[m],k[m+1]]=[k[m+1],k[m]];s+=i%2?"   X":"  X "}else{s+=i%2?"   |":"  | "}}s+="\n"}s+="\n "+a;alert(s)

Wyjaśnienie

Najpierw zastępuję dane wejściowe numerem indeksu i zmieniam pierwszy wiersz z wynikami. Na przykład

3 1 4 2
v v v v substitude with
1 2 3 4

so the first line will become:
1 2 3 4
v v v v
2 4 1 3

sorting 1,2,3,4 to 3,1,4,2 is equivalent to 2,4,1,3 to 1,2,3,4

Z tym podstawieniem mogę użyć algorytmu sortowania bąbelkowego, aby posortować 2,4,1,3 do 1,2,3,4, a wykres będzie najkrótszym możliwym, którego szukamy.
Jeśli masz jakieś pomysły, jak mogę zmniejszyć kod, po prostu skomentuj :)

Przykład

input: 3 4 2 1 7 5 6
output:
 1 2 3 4 5 6 7
 \ / \ / \ / \
  X   |   |   | 
 / \ / \ / \ /
|   X   |   X
 \ / \ / \ / \
  X   X   X   | 
 / \ / \ / \ /
|   X   |   |
 \ / \ / \ / \
 3 4 2 1 7 5 6

izlin
źródło
(1) Widzę, że używasz znacznika BR w trzech miejscach, więc możesz trochę zaoszczędzić, umieszczając to w zmiennej. Prawdopodobnie możesz także użyć \ n od czasu wyjścia na PRE.
JeffSB,
(2) Próbowałem różnych sposobów radzenia sobie z golfem JavaScript, a także wygodnego wprowadzania i wyświetlania. Myślę, że podoba mi się moja najnowsza metoda zainspirowana twoją podpowiedzią i ostrzeżeniem ... Używam podpowiedzi i ostrzeżenia w kodzie, aby można go było wkleić do konsoli i działa dla każdego. Ale zrobiłem też stronę z TEXTAREA i PRE, aby pokazać, że działa. Strona zastępuje podpowiedzi i ostrzeżenia dotyczące używania TEXTAREA i PRE - więc jest to ten sam kod i jest mniej zamieszania - może?
JeffSB
@JeffSB Użyłem <br>tagu i textarea tylko na jsfiddle, ponieważ wygląda znacznie lepiej. Alert nie ma czcionki o stałej szerokości, więc wynik wygląda źle. W mojej wersji golfowej używam alert i \ n. Czy twoja strona jest publiczna?
izlin
1

Kobra - 334 344 356 360

class P
    def main
        a,o,n=CobraCore.commandLineArgs[1:],['/','\\'],0
        c,l=a.count,a.sorted
        while (n+=1)%2or l<>a
            p,d='',(~n%4+4)//3
            for i in n%2*(c+1-c%2),p,o=p+o[1]+' ',[o.pop]+o
            for i in 1+d:c-n%2*c:2
                z=if(l[:i]<>a[:i],1,0)
                l.swap(i-z,i)
                p+=' ['|X'[z]]  '
            print[['','| '][d]+[p,p+'|'][d^c%2],p][n%2][:c*2]

Działa poprzez przesunięcie każdego elementu na miejsce, zaczynając od lewej. Z tego powodu często generuje absurdalnie dużą (choć nadal poprawną) mapę ścieżki.

Przykłady:

3 1 4 2

\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
 X   X  
/ \ / \ 
|  X  |
\ / \ / 
Obrzydliwe
źródło