The Strange Unsorting Machine for Nefarious Purposes

18

3

Good Evening Golfers!

Your challenge is to completely unsort a series of numbers.

Input

Exactly 100 integers will be fed to your program. Your program may accept the input either as a file, or via stdin. Each integer will be separated by a newline character.

Those 100 integers will range from the minimal to the maximal values of a signed integer in your chosen language.

There will be no duplicate values. The values may be ordered, unordered or partially ordered - your program should be able to handle each case.

Output

The output must be each of the 100 integers, completely unsorted, each separated by a newline character. The output may be via stdout, or to a file.

Completely Unsorted means that no value is adjacent to any value which it would be adjacent to if the list were completely sorted in an ordered sequence.

Score

1 point per character, and lowest score wins. There is a bonus of -100 for any solution using no built in or library sorting functions. There is a bonus of -20 for any solutions using no built in random number functions.

I have tried to define this question as completely as possible. If you have any questions, please ask. If you have any comments on how I could do better next time, please let me know.

Fore!

lochok

Posted 2012-10-24T07:56:44.773

Reputation: 3 139

There are exactly 100 integers input, and there are no duplicate values (see under "Input") – lochok – 2012-10-24T08:54:55.463

Right you are, didn't spot that. – Strigoides – 2012-10-24T09:01:02.233

2

It's not a duplicate as such, but it's not very different to http://codegolf.stackexchange.com/questions/6487/code-golf-mix-the-nuts-so-that-none-of-the-same-kind-are-touching

– Peter Taylor – 2012-10-24T11:10:20.327

So many clever responses! I'll select shortest answer on Oct 31 at 8:10-Zulu – lochok – 2012-10-28T11:55:08.650

Answers

9

GolfScript (score 27 - 120 = -93)

~].,{{.2$<{\}*}*]}*.(;+2%n*

Note: that $ is referencing an element on the stack. There is sorting, but it's done with an manually coded bubble sort.

Thanks to Howard, for -90 => -92; and Ilmari, who inspired -92 => -93.

Peter Taylor

Posted 2012-10-24T07:56:44.773

Reputation: 41 901

Credit for such a concise answer, but (forgive me, as I don't speak or understand GolfScript) - wouldn't the ^ disqualify it from the -100 bonus? – lochok – 2012-10-24T12:50:39.640

1@lochok, the built-in sort function is $ - that's why I mentioned that the $ in the program aren't sorts (it's context-dependent). The majority of the program (28 of the 42 characters) defines the function ^; the first version, using the built-in sort, was only 14 characters. – Peter Taylor – 2012-10-24T12:55:43.537

Ahh - right. Thanks for the clarification! – lochok – 2012-10-24T13:02:31.343

1You can save two chars with the following output loop: 2/{~p}%n*. – Howard – 2012-10-26T14:43:51.973

12/zip~+n* and .);\+2%n* also do the trick for the same number of chars as @Howard's version. Alas, I haven't managed to find anything shorter yet. – Ilmari Karonen – 2012-10-26T20:07:53.593

6

Python -26

(94-120): New, crude approach. Keep popping lowest elements into new list to get the elements sorted, then iterate:

t=l=[]
i=N=100
exec't=t+[input()];'*N+'l+=[t.pop(t.index(min(t)))];'*N+'print l[i%N];i+=3;'*N

Python -13

(107-120): First approach: Removes four lowest elements at a time, then print these four in another order:

exec'l=[]'+'+[input()]'*100
while l:
 a,b,c,d=eval('l.pop(l.index(min(l))),'*4)
 for e in[b,d,a,c]:print e

daniero

Posted 2012-10-24T07:56:44.773

Reputation: 17 193

t=l=[] and exec't+=[input()];'*100 would save you a few chars – quasimodo – 2012-10-26T16:48:55.673

also, you can use one exec statement for more than one loop. – quasimodo – 2012-10-26T17:33:50.443

@quasimodo I tried something like that, but with t=l=[] t and l point to the same object and it doesn't work. Skipping parentheses on exec is nice though. – daniero – 2012-10-26T19:31:44.527

You could use t=t+[input()];, this creates a new object each time. And you can even do the print loop in the exec statement: ';i+=1;print l[i*3%100]'*100. – quasimodo – 2012-10-27T10:53:12.480

You're right again. Thanks! Also added some other golfing like removing the %3 and avoiding repeation of 100. – daniero – 2012-10-28T13:30:44.247

One last tip: initialize i as 100 and use it instead of N :) – quasimodo – 2012-10-28T16:01:46.327

Clever :) However, I don't gain anything on removing N completely, as I then have to write i%100 and the total count will end up the same as now anyways. Unless you have another idea. – daniero – 2012-10-28T17:43:16.987

4

C: 11 (131 - 120)

The programm reads from stdin and does a simple insert sort, after that it prints the nth together with th n+50th number, like many of the other solutions.

main(){int*i,a[101],*j=a;while(scanf("%d",a)>0)for(i=++j;i-->a;)i[1]=*i>=*a?*i:*(i=a);while(a<(i=j-50))printf("%d\n%d\n",*i,*j--);}

quasimodo

Posted 2012-10-24T07:56:44.773

Reputation: 985

3

Ruby 1.9, -59

(61-120)

Recursion! This one does in fact, unlike my previous Ruby attempts, unsort the list regardless of their original order.

p *(f=->l{l[1]&&f[l-m=l.minmax]+m||[]})[$<.map &:to_i].rotate

Previous attempts

Cute one-liner, now using builtin sort to work properly:

$<.map(&:to_i).sort.each_slice(4){|a,b,c,d|p b,d,a,c}

First one -- Didn't necessarily unsort the last 4 values:

l=$<.map &:to_i
48.times{l-=p *l.minmax}
a,b,c,d=l
p b,d,a,c

daniero

Posted 2012-10-24T07:56:44.773

Reputation: 17 193

1Your -72 solution assumes the list starts out sorted, which is not the case. – histocrat – 2013-12-05T19:14:59.550

Oops. Seems I didn't re-read the question thoroughly when I revisited this one. Will try to come up with something else. – daniero – 2013-12-06T08:28:38.340

@histocrat that should do it. – daniero – 2013-12-11T16:14:27.730

3

J, -63 (57-120) characters

Since everyone else is going down the self-written sort route...

,50(}.,.{.)($:@([-.m),~m=.]#~]=<./)^:(0<#),".[;._2[1!:1[3

Doesn't use any random number function, nor any built-in sort.

Uses a simple recursive selection sort to sort the input.

Gareth

Posted 2012-10-24T07:56:44.773

Reputation: 11 678

3

Mathematica -56 44 4 (95-120) = -25

Edit:

This version relies on neither built-in functions for sorting lists, nor randomization functions.

Riffle[RotateLeft[#[[All, 2]], 2], #[[All, 1]]] &
[Partition[l //. {x___, a_, b_, y___} /; b < a :> {x, b, a, y}, 2]]

DavidC

Posted 2012-10-24T07:56:44.773

Reputation: 24 524

Is Sort not a built-in sort function? – Peter Taylor – 2012-10-24T22:56:59.503

You are correct! I missed the constraint about sort. – DavidC – 2012-10-24T23:20:17.540

I made a hand-rolled Sort. – DavidC – 2012-10-25T19:04:53.287

1

Perl 5: 95 - 120 = -25 chars

Counting the following command line:

perl -ne '$n=$_;splice@n,(grep{$n[$_]>$n}0..@n),0,$n}{print for map{@n[$_,$#n/2+$_+1]}0..$#n/2'

Matthias

Posted 2012-10-24T07:56:44.773

Reputation: 222

1

Ruby: -50 (70 chars - 120)

I did the same as many other answers: iteratively remove the max and min from the input list and append them to the output. However, I realized that if the 2 numbers on either side of the median are themselves consecutive, the output will be incorrect (because those 2 consecutive numbers will appear together at the end of the output). To fix this, I rotate the "unsorted" list right by 1 element:

n=$*.map &:to_i;u=[];50.times{u+=n.minmax;n-=u.last 2};p *u.rotate(-1)

Or, to work with arbitrarily many inputs (using only 4 more characters):

n=$*.map &:to_i;u=[];(u+=n.minmax;n-=u.last 2)while n.any?;p *u.rotate(-1)

Note: Some fewer-char Ruby answers have already been posted, but those solutions did not address the median issue (and/or assumed a sorted input list).

Jonathan Hefner

Posted 2012-10-24T07:56:44.773

Reputation: 61

1

J 37 - 100 = -63

({~?~@#)^:(+./@(1=|)@(2&(-/\))@/:)^:_

Uses no sort (though does use rank up) Uses random numbers.

Explanation:

({~?~@#)             NB. Randomizes the array
^: foobar ^:_        NB. as long as
foo =: +./@(1 = |)   NB. as any 1 == absolute value of
bar =: (2&(-/\))@/:  NB. differences between adjacent ranks
foobar =: foo@bar

jpjacobs

Posted 2012-10-24T07:56:44.773

Reputation: 3 440

1

Brachylog, 22 bytes - 120 = -98

ṇịᵐpX¬{p≤₁s₂.&s₂p}∧Xẉᵐ

Try it online!

The TIO link only has an input of eight integers, rather than one hundred, because this is so dreadfully slow that it can't handle any more in 60 seconds. The reason for this is that, among other things, rather than implement some simple but normal sorting algorithm for the mandatory bonus, I for the sake of brevity used what amounts to a deterministic bogosort: p≤₁ backtracks through every permutation of the input until it finds one which is non-decreasing. Although a larger reason would probably be that it employs a similar degree of brute force to find the output, and that it recomputes the sorted version every time... I attempted to test it on an actual input of size 100, but I'm not sure just how many days it will take.

An overall better version:

Brachylog, 14 bytes - 20 = -6

p.¬{os₂.&s₂p}∧

Try it online!

This ignores the antiquated I/O requirements for brevity, and neglects to take the -100 bonus so it can possibly be tested without a supercomputer (although as of writing this, I've had it running on only 20 items for several minutes and it still hasn't given me anything).

 .                The output is
p                 a permutation of
                  the input
  ¬{        }∧    such that it cannot be proven that
         s₂       a pair of adjacent values in
        &         the output
       .   p      is a permutation of
     s₂           a pair of adjacent values in
    o             the output sorted.

Unrelated String

Posted 2012-10-24T07:56:44.773

Reputation: 5 300

Although this isn't exactly a practical answer, it could be of use for validating the output from other programs, since most of it is just describing the constraint placed on the output. – Unrelated String – 2019-04-05T20:36:00.457

1

Python 2: 90 char

n=100
s=sorted(int(raw_input())for i in range(n))
for i in range(n):print s[(4*i+4*i/n)%n]

lazy attempt but just for starters

miles

Posted 2012-10-24T07:56:44.773

Reputation: 15 654

1

Python 27 (147 - 100 - 20)

R=range
def S(L):
 for i in R(len(L)-1):
    if L[i]>L[i+1]:L[i:i+2]=[L[i+1],L[i]];S(L)
a=map(input,['']*100);S(a)
for i in R(100):print a[i/2+i%2*50]

Note: the spaces before if L[i]>... should be a tab but apparently show up as spaces in a code block.

Matt

Posted 2012-10-24T07:56:44.773

Reputation: 1 395

With R=range you could save 5 characters. – scleaver – 2012-10-24T19:18:28.633

a=map(input,['']*100) – ugoren – 2012-10-26T05:33:42.220

1

Python 48 = (148 - 100)

from random import*
x=[input()for i in range(100)]
while any(abs(x[i]-x[i+1])>1 for i in range(99)):n=randint(1,99);x=x[n:]+x[:n]
for j in x:print j

Haven't tested this because it isn't guaranteed (or likely) to run in any reasonable amount of time, but should work in theory given infinite time.

scleaver

Posted 2012-10-24T07:56:44.773

Reputation: 507

1x=map(input,['']*100) – ugoren – 2012-10-26T05:32:37.017

And I don't think you even need the extra []s, just any single character string. – job – 2012-11-01T17:24:42.363

0

Forth (gforth), 79 - 120 = -21 bytes

: f 100 0 do dup i 2 mod 4 * 2 - i + i 99 = i 0 = - 3 * + cells + @ . cr loop ;

Try it online!

Ignore antiquated input requirements and takes input as an address in memory where the numbers are stored.

Explanation

Loops through all numbers from 0 to 99. For each number (n):

  • If n is 0:
    • output the value at array address + 1
  • Else If n is 99:
    • output the value at array address + 98
  • Else If n is odd:
    • output the value at array address + (n + 2)
  • Else (n is even):

    • output the value at array address + (n - 2)
  • Output a newline

Code Explanation

: f               \ start new word definition
  100 0 do        \ loop from 0 to 99
    dup           \ duplicate the array address
    i             \ place the loop index on the stack
    2 mod 4 * 2 - \ convert to 2 if it's odd and -2 if it's even
    i +           \ add the result to the the loop index
    i 99 =        \ if i = 99 place -1 on top of the stack, else place a 0
    i 0 =         \ i i = 0 place -1 on top of the stack, else place 0
    - 3 *         \ subtract previous two results from each other and multiply by 3
\ the above line is used to avoid writing if/then by instead using math to get 98 and 1
    +             \ add result to existing result from above
    cells         \ multiply by the size of a single integer in memory
    +             \ add to the array's starting address
    @ . cr        \ get the value at the calculated address, print it, then print a newline
  loop            \ end the loop
;                 \ end the word definition

reffu

Posted 2012-10-24T07:56:44.773

Reputation: 1 361