| Bytes | Lang | Time | Link |
|---|---|---|---|
| 072 | JavaScript Node.js | 240704T192740Z | l4m2 |
| 079 | R | 240704T173403Z | int 21h |
| 066 | Perl 5.10 or higher | 180202T073556Z | Ton Hosp |
| 071 | Haskell | 180202T091131Z | Laikoni |
| 229 | C# | 130815T185939Z | user8865 |
| 3421 | GolfScript | 130711T061217Z | Volatili |
| 090 | Python | 130711T073557Z | Keith Ra |
| 100 | Perl | 130711T062045Z | breadbox |
| 029 | GolfScript | 130711T081519Z | Howard |
| 079 | Ruby 1.9 | 130711T011201Z | Paul Pre |
| 282 | Python | 130711T022835Z | WendiKid |
| 120 | Python2 | 130711T071450Z | Bakuriu |
| 254 | Python 2 | 130711T053319Z | miles |
JavaScript (Node.js), 72 bytes
f=x=>(i=1,k=x.find(c=>c>x[i++]))?[i,2,i--,...f(x,x[i-1]=x[i],x[i]=k)]:[]
Bubble sort
Not directly comparable as I didn't do IO. Also reverse is long
R, 79 bytes
\(v)for(j in sum(v|1):2){v[1:w]=v[(w=which.max(v)):1];v=rev(v[-1]);cat(w,j,"")}
A function that takes in an unsorted array and prints out the flipping sequence to sort the array. The algorithm is the one described on Wikipedia1.
for(j in sum(v|1):2)run \$n-1\$ iterations, where \$n\$ is the size of the array to sort;w=which.max(v)find the position of the largest number;v[1:w]=v[w:1]insert the spatula between the largest pancake and the next one. Flip the upper pancakes so that the largest one gets on top;v=rev(v[-1])flip the whole heap of pancakes, so that the largest is at the bottom and remove it from the heap;cat(w,j,"")output both flips.
Now, the resulting sequence will always have \$(n-1)Ć2\$ flips, which is unnecessary long. Some flips could be skipped, like 1 or two flips of the whole stack - both of them do not change the order of pancakes. For instance, the sequence 6 5 4 1 2 3 will produce the flip sequence 1 6 5 5 4 4 1 3 2 2, in which only 6 and 3 are important - other flips could be ignored.
The reason why those redundant flips do appear in the output is to have the code as short as possible.
Perl 5.10 (or higher), 66 bytes
Includes +3 for -n
The use 5.10.0 to bring the language to level perl 5.10 is considered free
#!/usr/bin/perl -n
use 5.10.0;
$'>=$&or$.=s/(\S+) \G(\S+)/$2 $1/*say"$. 2 $."while$.++,/\S+ /g
Run with the input as one line on STDIN:
flop.pl <<< "1 8 3 -5 6"
Sorts the list by repeatedly finding any inversion, flipping it to the front then flipping the inversion and flipping everything back to its old position. And that is equivalent to swapping the inversion so I don't need to reverse (which is awkward on strings since it would reverse the digits of the values converting e.g. 12 to 21)
Haskell, 72 71 bytes
h s|(a,x:b)<-span(<maximum s)s=map length[x:a,s]++h(reverse b++a)
h e=e
Try it online! Finds the maximum, flips it to the back and recursively sorts the remaining list.
Edit: -1 byte thanks to BMO
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--);}}}
readable version
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--);
}
}
}
GolfScript, 34 / 21 chars
(Thanks @PeterTaylor for chopping 4 chars off)
~].{,,{1$=}$\}2*${.2$?.p)p.@\-+}/,
A shorter, 21 character version works for lists with unique items only
~].${.2$?.p)p.@\-+}/,
Both versions produce sub-optimal solutions.
Explanation for the shorter solution:
~] # 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
This uses a different algorithm to most of the others posted. Basically it grabs the smallest element of the list, and with two flips moves it to the front, preserving the other elements' order.
To move the nth element to the front:
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
It repeats this operation for each element in order, and ends up with a reverse sorted list. It then flips the whole list to leave it fully sorted.
In fact the algorithm is a variation of a 90-char Python solution (my own, of course):
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
Python, 91 90 chars
L=map(int,raw_input().split())
while L:i=L.index(max(L));print-~i,len(L),;L=L[:i:-1]+L[:i]
Flip the biggest pancake to the top, then flip the whole stack. Remove the biggest pancake from the bottom and repeat.
i is the index of the biggest pancake. L=L[:i:-1]+L[:i] flips i+1 pancakes, flips len(L) pancakes, then drops the last pancake.
Perl, 103 100 characters
Expects input on the command line.
for(@n=sort{$ARGV[$a]<=>$ARGV[$b]}0..$#ARGV;@n;say$i+1,$/,@n+1)
{$i=pop@n;$_=@n-$_-($_<=$i&&$i)for@n}
The solutions it prints are decidedly sub-optimal. (I had a program with much nicer output about 24 characters ago....)
The logic is kind of interesting. It starts by cataloguing the index of each item, were it in sorted order. It then iterates through this catalog from right to left. So applying a flip involves adjusting indexes below the cutoff value, instead of actually moving values around. After some finagling I also managed to save a few characters by doing both flips per iteration simultaneously.
GolfScript, 31 29 characters
~].${1$?).p.2$.,p>-1%\@<+)}%,
Another GolfScript solution, can also be tested online.
Previous version:
~].$-1%{1$?).2$>-1%@2$<+.,\);}/
How does it work: it flips the largest item to the top and then to the last place in the list. Since it is now in the correct position we can remove it from the list.
~] # 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
}/
Ruby 1.9 - 109 88 79 characters
Much more compact version based on Keith's great python solution:
a=$*.map &:to_i;$*.map{p v=a.index(a.max)+1,a.size;a=a[v..-1].reverse+a[0,v-1]}
Original version:
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}}
If you don't care about spurious operations (reversing stacks of size 1, or reversing the same stack twice in a row) you can make it a bit shorter (96 chars):
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}}
Takes the unsorted list as command-line args. Example usage:
>pc.rb 4 2 3 1
4
2
3
2
Python - 282 characters
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
My first ever code golf; I'm under no illusions I'll win, but I had a lot of fun. Giving everything one-character names sure makes it frightening to read, let me tell you! This is run from the command line, sample implementation below:
Python PancakeSort.py "4 2 3 1"
[1, 3, 2, 4]
[2, 1, 3, 4]
[1, 2, 3, 4]
There's nothing particularly special or inventive about the way I've gone about this, but the FAQ suggests posting a non-golfed version for interested readers, so I've done so below:
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
The basic algorithm I used is the one mentioned in the wiki article linked in the question:
The simplest pancake sorting algorithm requires at most 2nā3 flips. In this algorithm, a variation of selection sort, we bring the largest pancake not yet sorted to the top with one flip, and then take it down to its final position with one more, then repeat this for the remaining pancakes.
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
It's not efficient: it wont find the best sorting sequence, and the given sequence can even contain no-ops(i.e. flipping only the first element), nevertheless the output is valid.
The output is given in the form:
n_1 n_2
n_3 n_4
n_5 n_6
...
Which should be read as the sequence of flips: n_1 n_2 n_3 n_4 n_5 n_6 ....
If you want to obtain an output like:
n_1 n_2 n_3 n_4 n_5 n_6 ...
Simply add a comma in the print statement.
Python 2 (254)
Simple BFS-search, some stuff is inlined, probably could be compressed more without changing the search style. Hopefully this shows maybe how to start golfing a bit (too much to be in a simple comment).
Use:
python script.py 4 2 3 1
(2 spaces = tab)
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