Saygısız krep


27

Olarak yassı sıralama sadece izin verilen işlem dizisinin bir ön ek elemanlarını değiştirmektir. Veya bir yığın krep düşünün: Bir yığın spatulayı bir yere yerleştiririz ve tüm krepleri spatülün üstünden çeviririz.

Örneğin, 6 5 4 1 2 3ilk önce ilk 6elemanlar (tüm dizi) 3 2 1 4 5 6çevrilerek, ara sonuç elde edilerek ve sonra 3gelen ilk elemanlar çevrilerek sıralanabilir 1 2 3 4 5 6.

Sadece bir işlem olduğu için, bütün sıralama süreci, bir tam sayı dizisi ile tanımlanabilir, burada her bir tam sayı, pr çevirisini içerecek eleman / krep sayısıdır. Yukarıdaki örnek için, sıralama sırası olacaktır 6 3.

Başka bir örnek: 4 2 3 1ile sıralanabilir 4 2 3 2. İşte ara sonuçlar:

         4 2 3 1
flip 4:  1 3 2 4
flip 2:  3 1 2 4
flip 3:  2 1 3 4
flip 2:  1 2 3 4

Görev:

Tamsayıların listesini alan ve geçerli bir krep sıralama dizisi basan bir program yazın.

Sıralanacak liste, stdin'den boşlukla ayrılmış bir liste veya komut satırı argümanları olabilir. Listeyi yazdırın, ancak biraz okunabilir olduğu sürece uygun.

Bu kodgolf!

Düzenle:

Yorumlarda söylediğim gibi , çıktıyı optimize etmeniz gerekmez (en kısa sırayı bulmak NP-zordur ). Bununla birlikte , ucuz bir çözümün istediğiniz sonucu ([yeni?] Bir bogosort türü) elde edene kadar rasgele sayılar atmak olacağını fark ettim. Şimdiye kadarki cevapların hiçbiri bunu yapmadı , bu yüzden şimdi algoritmanızın herhangi bir (sözde) rastgeleliğe güvenmemesi gerektiğini ilan ediyorum .

Hepiniz tekmelemekle birlikte, Ruby 2.0'da (60 karakter) bir bogopancakesort çeşidi var.

a=$*.map &:to_i
a=a[0,p(v=rand(a.size)+1)].reverse+a[v..-1]while a!=a.sort

1
Herhangi bir geçerli dizi, yoksa en az bir uzunluk olmalıdır?
Peter Taylor

Küçük yazım hatası: ikinci örnek 4 3 2 1bunun yerine gösterir4 2 3 1
beary605

4
(Bunu düzenlemeye çalışırken internetim bozuldu, bu yüzden tekrar gönderdim) @PeterTaylor Buna bir çeşit optimizasyon eklemek için cazip oldum, ancak seçmedim. Minimal dizinin uzunluğunu bulmak aslında NP-zordur , en basit, yalındır algoritması en fazla 2n uzunluğunda bir çözüm bulabilir. Bunu bir kod-meydan okuma / optimal çıktı olayı olarak nasıl değerlendireceğimi gerçekten bilmiyorum ve sadece normal kodlayıcıyı daha çok seviyorum :)
daniero

Kimse girişini bu zorlukla gönderecek mi merak ediyorum .
grc

Sıra bitişik değerler olmak zorunda mı? 2 7 5 geçerli bir girdi mi?

Yanıtlar:


6

GolfScript, 34/21 karakter

(Teşekkürler @ 4 karakter kesmek için PeterTaylor)

~].{,,{1$=}$\}2*${.2$?.p)p.@\-+}/,

Çevrimiçi test

Daha kısa, 21 karakterlik bir sürüm yalnızca benzersiz öğelere sahip listeler için çalışır

~].${.2$?.p)p.@\-+}/,

Çevrimiçi test

Her iki versiyon da en düşük düzeyde çözümler üretiyor.


Kısa çözüm için açıklama:

~]         # read input from stdin
.$         # produce a sorted copy from lowest to highest
{          # iterate over the sorted list
  .2$?     # grab the index of the element
  .p       # print the index
  )p       # increment and print the index
  .@\-+    # move the element to the front
}/
,          # leave the length of the list on the stack
           # this flips the reverse sorted list to become sorted

Bu yayınlanan diğer çoğu için farklı bir algoritma kullanır. Temel olarak listenin en küçük elemanını alır ve iki kapaklı diğer elemanların sırasını koruyarak öne doğru hareket ettirir.

Nth öğesini öne doğru taşımak için:

1 2 3 4 5 6 7   # let's move the 3rd (0-based) element to the front
# flip the first 3 elements
3 2 1 4 5 6 7
# flip the first 3+1 elements
4 1 2 3 5 6 7

Her eleman için bu işlemi sırayla tekrarlar ve tersine sıralanan bir liste ile sona erer. Daha sonra tamamen sıralanmış olarak bırakmak için tüm listeyi çevirir.


Aslında, algoritma 90-char Python çözümünün bir çeşididir (elbette kendi):

d=map(int,raw_input().split());i=0
while d:n=d.index(max(d));d.pop(n);print n+i,n-~i,;i+=1

2
GolfScript'in kullanışlı özelliklerinden birine rastlamadığınızı görüyorum: herhangi bir jetonu değişken olarak kullanabilirsiniz. Kullanmadığınız &Değiştirmeye gerekir, böylece hiçbir yerinde siken &ve boşluk kaldırmak.
Peter Taylor

@PeterTaylor, neden ^fibonacci mücadelesinde bir değişken olarak kullanabileceğinizi merak ediyordum ;) Tavsiyeniz için teşekkürler!
Oynaklık

Giriş 3 2 1için 131211doğru olanı alıyorum .
Howard,

@Howard şimdi işe koyuldu
Volatility

@Volatility Son değişiklik biraz fazlaydı ;-) Örneğin, listeler 2 1 1artık sıralanamıyor.
Howard,

11

Python, 91 90 karakter

L=map(int,raw_input().split())
while L:i=L.index(max(L));print-~i,len(L),;L=L[:i:-1]+L[:i]

En büyük krepi tepeye çevirin, ardından bütün yığını çevirin. En büyük gözleme altından çıkarın ve tekrarlayın.

ien büyük krepin endeksidir. krep L=L[:i:-1]+L[:i]çevirir, i+1krep çevirir len(L), sonra son krep düşer.


1
Sadece çekimler yapmana izin verildiğini sanıyordum. (Yani, yığından pankek bırakabileceğinizi düşünmedim). Kuralları yanlış mı anladım? Hmm. tekrar wiki sayfasını okumaya gider. Ne olursa olsun, güzel iş :) 100 karakterden az benim için oldukça şaşırtıcı!
WendiKidd

@WendiKidd Aslında, demek istediği, en büyüğünü aşağıya doğru çektikten sonra, onu görmezden gelmesi ve üzerine gözleme yapmasıdır.
AJMansfield

@ AJMansfield Ah, anlıyorum! Teşekkürler, bu mantıklı. Kodu okuyamıyorum (Python için çok yeniyim) bu yüzden açıklamayı yanlış anladım :) Teşekkürler!
WendiKidd

2
Neredeyse daha önce yazdıklarımın bir evrimi. Elemanları kaldırmayı düşünmedim çünkü başlangıçta çıktının doğruluğunu kontrol etmek zorunda kaldım (örneğin liste daha sonra sıralandı mı?). Bu arada: print
Virgülün çıkarılmayacağından

@WendiKidd, aslında, daha fazla inceleme yapıldığında, krepleri gerçekten yok ediyor; sadece dizilerin sıralamasını değil, sadece dizilerin ne olduğunu çözmesi gerekir.
AJMansfield

6

Yakut 1,9 - 109 88 79 karakter

Keith'in mükemmel python çözümünü temel alan çok daha kompakt versiyon:

a=$*.map &:to_i;$*.map{p v=a.index(a.max)+1,a.size;a=a[v..-1].reverse+a[0,v-1]}

Orijinal versiyon:

a=$*.map &:to_i
a.size.downto(2){|l|[n=a.index(a[0,l].max)+1,l].map{|v|v>1&&n<l&&p(v);a[0,v]=a[0,v].reverse}}

Sahte işlemlerle ilgilenmiyorsanız (1. büyüklükteki yığınları ters çevirerek veya aynı yığını üst üste iki kez ters çevirerek) umursamıyorsanız, biraz daha kısa yapabilirsiniz (96 karakter):

a=$*.map &:to_i
a.size.downto(2){|l|[a.index(a[0,l].max)+1,l].map{|v|p v;a[0,v]=a[0,v].reverse}}

Sıralanmamış listeyi komut satırı argümanları olarak alır. Örnek kullanım:

>pc.rb 4 2 3 1
4
2
3
2

6

GolfScript, 31 29 karakter

~].${1$?).p.2$.,p>-1%\@<+)}%,

Başka bir GolfScript çözümü de çevrimiçi olarak test edilebilir .

Önceki versiyon:

~].$-1%{1$?).2$>-1%@2$<+.,\);}/

Nasıl çalışır: en büyük maddeyi en üste ve ardından listedeki en son yere çevirir. Şimdi doğru konumda olduğundan listeden kaldırabiliriz.

~]         # Convert STDIN (space separated numbers) to array
.$-1%      # Make a sorted copy (largest to smallest)
{          # Iterate over this copy
  1$?)     # Get index of item (i.e. largest item) in the remaining list,
           # due to ) the index starts with one
  .        # copy (i.e. index stays there for output)
  2$>      # take the rest of the list...
  -1%      # ... and reverse it 
  @2$<     # then take the beginning of the list
  +        # and join both. 
           # Note: these operations do both flips together, i.e.
           # flip the largest item to front and then reverse the complete stack
  .,       # Take the length of the list for output
  \);      # Remove last item from list
}/

4

Perl, 103 100 karakter

Komut satırında girişi bekliyor.

for(@n=sort{$ARGV[$a]<=>$ARGV[$b]}0..$#ARGV;@n;say$i+1,$/,@n+1)
{$i=pop@n;$_=@n-$_-($_<=$i&&$i)for@n}

Yazdırdığı çözümler kesinlikle alt optimaldir. (24 karakter önce çok daha iyi çıktıya sahip bir programım vardı ....)

Mantık biraz ilginç. Her bir öğenin indeksini sıralayarak sırayla kataloglayarak başlar. Daha sonra bu katalog üzerinden sağdan sola doğru tekrar eder. Bu nedenle, bir flip uygulamak, aslında etrafında hareket eden değerler yerine, kesme değerinin altındaki indeksleri ayarlamayı içerir. Bazı finisajlardan sonra, aynı anda yineleme başına iki flips yaparak da birkaç karakter kaydetmeyi başardım.


3

Piton 2 (254)

Basit BFS-arama, bazı şeyler satır içi, muhtemelen arama stilini değiştirmeden daha fazla sıkıştırılabilir. Umarım bu belki biraz golf oynamaya nasıl başlayacağınızı gösterir (çok basit bir yorumda bulunmak için çok fazla).

kullanın:

python script.py 4 2 3 1

(2 boşluk = sekme)

import sys
t=tuple
i=t(map(int,sys.argv[1:]))
g=t(range(1,len(i)+1))
q=[i]
p={}
l={}
while q:
 c=q.pop(0)
 for m in g:
  n=c[:m][::-1]+c[m:]
  if n==g:
   s=[m]
   while c!=i:s+=[l[c]];c=p[c]
   print s[::-1]
   sys.exit()
  elif n not in p:q+=[n];p[n]=c;l[n]=m

1
Sen yerini alabilir sys.exit()ile 1/0(... codegolf size stderr'e basılmış çıkacak öğeler için bakım asla).
Bakuriu

Tabii, print s[::-1];1/0birkaç tane tıraş etmek için yapabilirim .
mil

BFS çok ilginç, ama onu çalıştıran 4 2 3 1verir 2 3 2 4aslında geçersiz olan.
daniero

1
@ daniero Bu çıktı nasıl geçersiz? 4 2 3 1-> 2 4 3 1-> 3 4 2 1-> 4 3 2 1->1 2 3 4
Gareth

@ Gareth Hiçbir fikrim yok! Ve iki kere bile kontrol ettim .. Oh, neyse boşver o zaman :) Güzel bir çözüm, mil t.
daniero

3

Python2: 120

L=map(int,raw_input().split())
u=len(L)
while u:i=L.index(max(L[:u]))+1;L[:i]=L[i-1::-1];L[:u]=L[u-1::-1];print i,u;u-=1

Verimli değildir: en iyi sıralama dizisini bulamaz ve verilen diziliş bile-op içeremez (yani yalnızca ilk elemanı çevirir), yine de çıktı geçerlidir.

Çıktı formda verilmiştir:

n_1 n_2
n_3 n_4
n_5 n_6
...

Hangi çevirir dizisi olarak okunmalıdır: n_1 n_2 n_3 n_4 n_5 n_6 .... Gibi bir çıktı elde etmek istiyorsanız:

n_1 n_2 n_3 n_4 n_5 n_6 ...

Basitçe printifadeye virgül ekleyin .


[:i][::-1]-> [i-1::-1], [:u][::-1]-> [u-1::-1], 2 karakter kazandırdı
Volatility

Aslında, L[:i]=L[i-1::-1];L[:u]=[u-1::-1]3 karakter daha kaydeder
Volatility

@Volatility Püf noktaları için teşekkürler. Dahil.
Bakuriu

3

Python - 282 karakter

import sys
s=sys.argv[1]
l=s.split()
p=[]
for c in l:
 p.append(int(c))
m=sys.maxint
n=0
while(n==(len(p)-1)):
 i=x=g=0
 for c in p:
  if c>g and c<m:
   g=c
   x=i
  i+=1
 m=g
 x+=1
 t=p[:x]
 b=p[x:]
 t=t[::-1]
 p=t+b
 a=len(p)-n;
 t=p[:a]
 b=p[a:]
 t=t[::-1]
 p=t+b
 print p
 n+=1

Benim ilk golf kodlarım; Yanılsamam yok , kazanacağım ama çok eğlendim. Her şeyi tek karakterli isimlerle vermek, okumayı korkutucu kılar, size söyleyeyim! Bu, aşağıdaki örnek uygulama komut satırından çalıştırılır:

Python PancakeSort.py "4 2 3 1"
[1, 3, 2, 4]
[2, 1, 3, 4]
[1, 2, 3, 4]

Bu konuya girme biçimim hakkında özellikle özel veya yaratıcı bir şey yok, ancak SSS ilgilenen okuyucular için golf oynamayan bir sürüm yayınlamayı öneriyor, bu yüzden aşağıda yaptım:

import sys

pancakesStr = sys.argv[1]
pancakesSplit = pancakesStr.split()
pancakesAr = []
for pancake in pancakesSplit:
    pancakesAr.append(int(pancake))

smallestSorted = sys.maxint
numSorts = 0

while(numSorts < (len(pancakesAr) - 1)):
    i = 0
    biggestIndex = 0
    biggest = 0
    for pancake in pancakesAr:
        if ((pancake > biggest) and (pancake < smallestSorted)):
            biggest = pancake
            biggestIndex = i
        i += 1

    smallestSorted = biggest  #you've found the next biggest to sort; save it off.
    biggestIndex += 1   #we want the biggestIndex to be in the top list, so +1.

    top = pancakesAr[:biggestIndex]
    bottom = pancakesAr[biggestIndex:]

    top = top[::-1] #reverse top to move highest unsorted number to first position (flip 1)
    pancakesAr = top + bottom   #reconstruct stack

    alreadySortedIndex = len(pancakesAr) - numSorts;

    top = pancakesAr[:alreadySortedIndex]
    bottom = pancakesAr[alreadySortedIndex:]

    top = top[::-1] #reverse new top to move highest unsorted number to the bottom position on the unsorted list (flip 2)
    pancakesAr = top + bottom   #reconstruct list

    print pancakesAr    #print after each flip

    numSorts += 1

print "Sort completed in " + str(numSorts) + " flips. Final stack: "
print pancakesAr

Kullandığım temel algoritma , soru ile bağlantılı wiki makalesinde bahsedilen algoritma :

En basit krep sıralama algoritması en fazla 2n − 3 döndürme gerektirir. Bu algoritmada, seçim türünün bir varyasyonunda, henüz bir çevirme ile en üste sıralanmamış en büyük krepi getiriyoruz ve daha sonra bir kepçe ile son konumuna getiriyoruz, sonra bunu kalan krepler için tekrar ediyorum.


1
Golf için bazı ipuçları: girinti için dört boşluk israflıdır. Daha iyi: bir boşluk kullanın; daha da iyisi: daha da fazla kesmek için tırnakları ve boşlukları birleştirin.
John Dvorak

1
t=p[:x] t=t[::-1](16 + girinti) t=p[:x][::-1](13) veya hatta t=p[x-1::-1](12) ' ye kadar düşürülebilir . Yapabileceğiniz her şeyi satır içi:p=p[x-1::-1]+p[x:]
John Dvorak

Arkadan saymak için negatif endeksleri kullanın. len(a)-nolur -n; p=p[-n-1::-1]+p[-n:]. Doğru işlemleri kullanarak daha fazla golf:p=p[~n::-1]+p[-n:]
John Dvorak

1
Umm ... Sadece sonuç değil, tüm çevirme sırasını yazdırmanız gerekiyor.
John Dvorak

Jan Dvorak'ın söylediği. Bu arada codegolf'a hoş geldiniz. Bazı basit önlemlerle karakter sayısını yarıya kadar kolayca kesebilirsiniz; Bazılarından söz edildi. Ayrıca, ara değişkenler iyi değildir. Liste anlama güzeldir. Ancak sys.argv kullanıyorsanız, girişin her sayısının argüman olmasına izin verebilirsiniz, o map(int,sys.argv[1:])zaman 6 ilk satırınızın şimdi yaptığı şeyi yapar. i=x=g=0çalışır, ancak yine de değişkenlerin miktarını azaltmalısınız. Yine de sana bir şey vereceğim: Bu en az anladığım bir python girişi: D
daniero

3

C # - 264 259 252 237 karakter

En basit algoritmayı kullanır ve yedekli çevirmeler olmadan doğru çıktı üretir. Çıktıda 1'leri (çevirmeyenler) dahil etmesine izin verirsem 7 kareyi tıraş ederdim, ama bu çirkin.

gotoMaksimum golf sahası için kullanmaya başladım. Ayrıca bazı karakterleri, çevirmeyenleri gerçekleştirmesine izin vererek kaydetti (ancak yazdırmadı).

En son gelişme: giriş dizisini inte dönüştürmek yerine karakter dizisi olarak tutmak.

using System.Linq;class P{static void Main(string[]a){var n=a.ToList();for(int p
=n.Count;p>0;p--){int i=n.IndexOf(p+"")+1;if(i<p){f:if(i>1)System.Console.Write
(i);n=n.Take(i).Reverse().Concat(n.Skip(i)).ToList();if(i!=p){i=p;goto f;}}}}}

Ungolfed:

using System.Linq;
class Program
{
    static void Main(string[] args)
    {
        var numbers = args.ToList();

        for (int pancake = numbers.Count; pancake > 0; pancake--)
        {
            int index = numbers.IndexOf(pancake+"") + 1;
            if (index < pancake)
            {
                flip:

                if (index > 1)
                    System.Console.Write(index);

                numbers = numbers.Take(index)
                                 .Reverse()
                                 .Concat(numbers.Skip(index))
                                 .ToList();

                if (index != pancake)
                {
                    index = pancake;
                    goto flip;
                }
            }
        }
    }
}

İşte benim ilk çözümüm, ungolfed (264 karakter golf oynadı):

using System.Linq;
using System;

class Program
{
    static void Main(string[] args)
    {
        var numbers = args.Select(int.Parse).ToList();

        Action<int> Flip = howMany =>
        {
            Console.Write(howMany);
            numbers = numbers.Take(howMany)
                             .Reverse()
                             .Concat(numbers.Skip(howMany))
                             .ToList();
        };

        for (int pancake = numbers.Count; pancake > 0; pancake--)
        {
            int index = numbers.IndexOf(pancake) + 1;
            if (index < pancake)
            {
                if (index > 1)
                    Flip(index);
                Flip(pancake);
            }
        }
    }
}

Bitişik olmayan dizileri işlemez - bu girdilerle yanlış sonuç verir.

@hatchet: Ne demek istediğinden emin değilim. Bana bir örnek verebilirmisin?
Igby Largeman,

1 22'lik bir girdi göz önüne alındığında, sonuç 22'de 1 olacak sonuçta bir takas yapılması gerektiğini söylüyor. Kodunuzun dizinin bitişik sayıları içermesini beklediğini düşünüyorum (örneğin: 2 4 1 3), ancak ( 2 24 5 5 990).

@hatchet: Gerçekten, dizilimdeki boşlukları desteklemeye çalışmıyorum, çünkü bu mantıklı olmaz. Krep sıralaması fikri, bir rasgele sayı grubunu değil, bir nesne yığınını sıralamaktır. Her nesneyle ilişkili sayı yığındaki uygun konumunu tanımlar. Bu nedenle sayılar her zaman 1 ile başlayacak ve bitişik olacaktır.
Igby Largeman

Emin değildim, çünkü soru "dizi" dedi ve matematikte {1, 22} geçerli bir dizidir, ancak her iki örnek de bitişik sayılardı. Bu yüzden OP'den açıklama istedi (soru hakkındaki yorumlara bakınız). Bence buradaki cevapların çoğu boşlukları kaldıracak.

2

Haskell , 72 71 bayt

h s|(a,x:b)<-span(<maximum s)s=map length[x:a,s]++h(reverse b++a)
h e=e

Çevrimiçi deneyin! Maksimumları bulur, geriye doğru çevirir ve kalan listeyi tekrar tekrar sıralar.

Düzenleme: BMO sayesinde -1 bayt


2

5,10 Perl (veya üstü), 66 bayt

Kapsar +3için 5.10 ücretsiz kabul edilir perl seviyeye dili getirmek-nuse 5.10.0

#!/usr/bin/perl -n
use 5.10.0;
$'>=$&or$.=s/(\S+) \G(\S+)/$2 $1/*say"$. 2 $."while$.++,/\S+ /g

STDIN'de giriş ile bir satır olarak çalıştırın:

flop.pl <<< "1 8 3 -5 6"

Listeyi sırayla herhangi bir inversiyon bularak, öne doğru çevirip sonra ters çevirmeyi ve her şeyi eski konumuna geri çevirerek sıralar. I ters gerek kalmaz ve bu inversiyon pompalanması eşdeğerdir (bu dönüştürme değerleri basamak ters zira tellerde zor olan, örneğin 12için 21)


1

C # - 229

using System;using System.Linq;class P{static void Main(string[] a){
var n=a.ToList();Action<int>d=z=>{Console.Write(z+" ");n.Reverse(0,z);};
int c=n.Count;foreach(var s in n.OrderBy(x=>0-int.Parse(x))){
d(n.IndexOf(s)+1);d(c--);}}}

okunabilir sürüm

using System;
using System.Linq;
class P {
    static void Main(string[] a) {
        var n = a.ToList();
        Action<int> d = z => { Console.Write(z + " "); n.Reverse(0, z); };
        int c = n.Count;
        foreach (var s in n.OrderBy(x => 0 - int.Parse(x))) {
            d(n.IndexOf(s) + 1); d(c--);
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.