The Daily WTF: Curious Perversions in Information Technology
Welcome to TDWTF Forums Sign in | Join | Help
in Search

15th Speed Challenge

Last post 05-19-2007 10:56 AM by Autonuke. 15 replies.
Page 1 of 1 (16 items)
Sort Posts: Previous Next
  • 05-15-2007 8:20 AM

    15th Speed Challenge

    This is somewhat of a classic problem, so I hope there's no comp-sci people around who have solved it forwards backwards and in scheme...

    Given a cooking time and a pair of egg timers, determine the order in which you should flip the timers to meet the required time.

    For example, eggtimer 60 40 50 (60s cooking time, egg timers of 40s and 50s size) should yield something like:

    Begin: start cooking, flip 40s, flip 50s
    When 40s runs out: flip 40s
    When 50s runs out: flip 40s
    When 40s runs out: stop cooking 

    If you find an efficient answer early, here's a few additional items to keep it interesting:
    * Handle the case where I don't start cooking in the first step
    * Handle the case in which I use my quantum egg timers that run out of sand before you flip them
    * Handle the case when I acquire three or more egg timers. 

  • 05-16-2007 10:54 AM In reply to

    Re: 15th Speed Challenge

    This one can only solve very simple problems (I'd need to build a backtracking thingy into the target loop otherwise), but it lets you specify an arbitrary amount of sandglasses:
     
    # eggtimers.py
    
    def others(one, all_):
        for another in all_:
            if another == one:
                continue
            yield another
    
    target = int(raw_input("Please specify the target time.\n"))
    sandglasses = map(lambda x: int(x), raw_input("Please specify the size of \
    the sandglasses.\n").split())
    sandglasses.sort(None, None, True)
    
    solution = []
    selected = [0, 0]
    while target > 0:
        found = False
        for glass in sandglasses:
            if glass <= target:
                target -= glass
                selected = [glass, 0]
                found = True
                break
        if not found and not selected[1]:
            for other in others(selected[0], sandglasses):
                diff = abs(selected[0] - other)
                if diff <= target:
                    solution.pop()
                    target -= diff
                    selected[1] = other
                    found = True
                    break
        if not found:
            print "No solution was found."
            break
        solution.append(selected)
    
    if found:
        prevglass = ""
        print "Solution:"
        for step in solution:
            if not prevglass:
                if step[1]:
                    print "Flip the %ds and %ds sandglasses.\nWhen %ds runs out, \
    flip %ds." % (step[0], step[1], step[1], step[0])
                else:
                    print "Flip the %ds sandglass." % step[0]
                prevglass = step[0]
                continue
            if step[1]:
                print "When %ds runs out, flip the %ds and %ds sandglasses.\n\
    When %ds runs out, flip %ds." % (prevglass, step[0], step[1], step[1], step[0])
            else:
                print "When %ds runs out, flip the %ds sandglass." % (
                    prevglass, step[0])
            prevglass = step[0]
        print "When %ds runs out, your egg is cooked." % prevglass
    
    rpar PROTON all
  • 05-16-2007 11:35 AM In reply to

    Re: 15th Speed Challenge

    That works pretty well with just a simple algorithm.  I didn't think of the greedy/change-making algorithm here.

    Faxmachinen gets the next problem.
     

  • 05-17-2007 2:25 PM In reply to

    Speed Challenge 0x10: Comparison

    Speed Challenge 0x10: Comparison
     
    Write your favorite sorting algorithm. This time however, you're not allowed to use any comparison operators anywhere in your program.
    Your program should take a list of numbers as input, and spit the sorted list back out.
    rpar PROTON all
  • 05-17-2007 4:07 PM In reply to

    Re: Speed Challenge 0x10: Comparison

    Faxmachinen:
    Speed Challenge 0x10: Comparison
     
    Write your favorite sorting algorithm. This time however, you're not allowed to use any comparison operators anywhere in your program.
    Your program should take a list of numbers as input, and spit the sorted list back out.

    echo 1 2 6 7 | perl -e '$/ = " "; (/(\d+)/ && $v{$1}++) while <>; while (scalar %v) {my $x = $i++; my $c = delete $v{$x}; print "$x " x $c}; print "\n"'

    Works only for the natural numbers.

    (It's quite tricky to write anything without using ==, eq, or grep, hence the $/ and regexp dance for input parsing) 

  • 05-17-2007 6:55 PM In reply to

    Re: Speed Challenge 0x10: Comparison

    My solution is a tad longer than asuffield's, but it does work with negative integers. Besides, there's too little Prolog on this site.

    % peanosort.pro  run :-  	prompt1('Enter a list of integers: '), 	read(List),  	sort_list(List, Sorted),  	nl, write('Sorted: '), write(Sorted), nl.  /*	sort_list(+List, ?ListSorted)  	Normalise a list of integers, sort it, 	de-normalise it, print it. */ sort_list(L, S):- 	normalised(L, LN), 	sort_normalised(LN, SN), 	normalised(S, SN).  /* 	normalised(+List, ?ListNormalised) 	normalised(?List, +ListNormalised) 	 	Turn any negative numbers into terms of the form minus(Natural)	 */ normalised([], []). normalised([H|T], [HN|TN]):- 	normal(H, HN), 	normalised(T, TN).  /*	normal(+Integer, ?Normal)  	normal(?Integer, +Normal)  	 	A negative number does not match the term -Variable,  	so put in explicit minus(N) term  */ normal(N, minus(NN)):- 	integer(NN), !,	  % if NN is bound, we're de-normalising 	N is -1 * NN. normal(N, minus(NN)):- 	not(abs(N, N)), !, 	NN is -1 * N. normal(N, N).  /*	sort_normalised(+List, ?Sorted) 	 	Do the actual sorting */ sort_normalised([], []). sort_normalised([H|T], S):- 	sort_normalised(T, S1), 	insert(H, S1, S).  insert(N, [], [N]). insert(N, [H|T], [N,H|T]):-  	lte(N, H), !. insert(N, [H|T], [H|U]):- 	insert(N, T, U).  /*	lte(+N, +M) 	 	N less-than-or-equal-to M */ lte(N, N):- !. lte(minus(N), minus(M)):- !, 	lte(M, N). lte(minus(_), _):- !. lte(_, minus(_)):- !, fail. lte(N, M):- 	peano(N, PN), 	peano(M, PM), 	succeeds(PM, PN).  /*	peano(+Natural, ?PeanoRepr)  	Peano representation of a natural number */ peano(0, 0):- !. peano(N, succ(P)):-  	M is N - 1, 	peano(M, P).  /*	succeeds(+P, +Q) 	 	P succeeds Q */ succeeds(succ(P), P). succeeds(succ(P), Q):- 	succeeds(P, Q).  


    This is, of course, cheating.

    (To run the program, download, install and run SWI-Prolog. 'Consult' (see file menu) the file with the above code. At the ?- prompt, enter run. (including the full stop). When it asks you for a list of integers, enter that list as you would a Python list, terminated with a full stop, for example [2, -3, 1].)
  • 05-17-2007 7:04 PM In reply to

    Re: Speed Challenge 0x10: Comparison

    Let's try that again:

     % peanosort.pro

    run :-
    prompt1('Enter a list of integers: '),
    read(List),
    sort_list(List, Sorted),
    nl, write('Sorted: '), write(Sorted), nl.

    /* sort_list(+List, ?ListSorted)

    Normalise a list of integers, sort it,
    de-normalise it, print it.
    */
    sort_list(L, S):-
    normalised(L, LN),
    sort_normalised(LN, SN),
    normalised(S, SN).

    /* normalised(+List, ?ListNormalised)
    normalised(?List, +ListNormalised)

    Turn any negative numbers into terms of the form minus(Natural)
    */
    normalised([], []).
    normalised([H|T], [HN|TN]):-
    normal(H, HN),
    normalised(T, TN).

    /* normal(+Integer, ?Normal)
    normal(?Integer, +Normal)

    A negative number does not match the term -Variable,
    so put in explicit minus(N) term
    */
    normal(N, minus(NN)):-
    integer(NN), !, % if NN is bound, we're de-normalising
    N is -1 * NN.
    normal(N, minus(NN)):-
    not(abs(N, N)), !,
    NN is -1 * N.
    normal(N, N).

    /* sort_normalised(+List, ?Sorted)

    Do the actual sorting
    */
    sort_normalised([], []).
    sort_normalised([H|T], S):-
    sort_normalised(T, S1),
    insert(H, S1, S).

    insert(N, [], [N]).
    insert(N, [H|T], [N,H|T]):-
    lte(N, H), !.
    insert(N, [H|T], [H|U]):-
    insert(N, T, U).

    /* lte(+N, +M)

    N less-than-or-equal-to M
    */
    lte(N, N):- !.
    lte(minus(N), minus(M)):- !,
    lte(M, N).
    lte(minus(_), _):- !.
    lte(_, minus(_)):- !, fail.
    lte(N, M):-
    peano(N, PN),
    peano(M, PM),
    succeeds(PM, PN).

    /* peano(+Natural, ?PeanoRepr)

    Peano representation of a natural number
    */
    peano(0, 0):- !.
    peano(N, succ(P)):-
    M is N - 1,
    peano(M, P).

    /* succeeds(+P, +Q)

    P succeeds Q
    */
    succeeds(succ(P), P).
    succeeds(succ(P), Q):-
    succeeds(P, Q).
  • 05-18-2007 6:17 AM In reply to

    • flop
    • Top 500 Contributor
    • Joined on 04-27-2007
    • Posts 57

    Re: Speed Challenge 0x10: Comparison

    Faxmachinen:
    This time however, you're not allowed to use any comparison operators anywhere in your program.

    If I read that correctly (wrong :-), that means no simple loops either ... since every "normal" loop has some comparison for stopping.

    But that's not what you mean, I believe.

     

    Strictly that seems to be unsolveable ... even 'is this the last number' is some comparison ...

    If we lower the bar to say (assembler) "cmp" is not allowed, but "jnz", "js" is - then it's a trivial work, since every "compare a,b" can be rewritten as "is (a-b) <, >, == 0".

  • 05-18-2007 7:08 AM In reply to

    Re: Speed Challenge 0x10: Comparison

    flop:
    Faxmachinen:
    This time however, you're not allowed to use any comparison operators anywhere in your program.

    If I read that correctly (wrong :-), that means no simple loops either ... since every "normal" loop has some comparison for stopping.

    You can assemble working loops out of Church booleans, in a pinch. The Church 'true' is the function tru(x, y) {return x;} and 'false' is fls(x, y) {return y;}. You store a pointer to one of these two functions as your 'boolean' value, and the conditional 'x ? y : z' is written as 'x(y, z)'.

    I really can't be bothered to put together a solution like that, though. It would be basically equivalent to the one I already posted, just harder to understand. 

  • 05-18-2007 7:19 AM In reply to

    • flop
    • Top 500 Contributor
    • Joined on 04-27-2007
    • Posts 57

    Re: Speed Challenge 0x10: Comparison

    How about that?
    $ echo 1.3 0.6 0.2 1.2 | perl sort-without-cmp.pl
    0.2
    0.6
    1.2
    1.3
    
    The program:
    #!/usr/bin/perl
    
    $/=" ";
    $|=1;
    $^F=0;
    pipe R, W;
    while (<>)
    {
            next unless ($_+=0) >0;
            $i=fork();
            if (!$i)
            {
                    close W;
                    sysread(R, $i, 1);
                    select(undef, undef, undef, $_);
                    print $_,"\n";
                    exit;
            };
            push @i, $i;
    }
    
    close R;
    close W;
    wait for (@i);
    
    Please note that this solution does not really scale.
  • 05-18-2007 9:06 AM In reply to

    Re: Speed Challenge 0x10: Comparison

    flop:
    If I read that correctly (wrong :-), that means no simple loops either ... since every "normal" loop has some comparison for stopping.
    True, I should have specified "sourcecode" instead of "program". I don't care much what does on behind the scenes.
    And you can indeed use (A - B) to determine if A != B, but the lesser-than and greater-than comparisons require a bit more work.
    rpar PROTON all
  • 05-18-2007 9:42 AM In reply to

    • flop
    • Top 500 Contributor
    • Joined on 04-27-2007
    • Posts 57

    Re: Speed Challenge 0x10: Comparison

    Faxmachinen:
    And you can indeed use (A - B) to determine if A != B, but the lesser-than and greater-than comparisons require a bit more work.

    sub a, b
    js smaller
    
    Or you don't allow "js" (jump if sign bit set) ... but then most loops are not allowed.

    If only "JZ" (jump if zero) is possible, it doesn't matter much ...

    sub a, b
    and a, 0x80000000
    jz smaller
    
    does more or less the same.

    But I think my contribution satisfies your wishes.

  • 05-18-2007 10:01 AM In reply to

    Re: Speed Challenge 0x10: Comparison

    edit - nvm, found an error and post delete doesn't work.
  • 05-18-2007 10:58 AM In reply to

    Re: Speed Challenge 0x10: Comparison

    Probably cheating. My favorite sorting algorithm is whatever someone else implemented:

    #!/bin/bash
    if [ -d sorttemp ]
    then
       rm -rf sorttemp
    fi
    mkdir sorttemp
    for param in $*
    do
       touch sorttemp/$param
    done
    # Make all numbers the same # of digits
    # maxint is about 4000000000 so 10 digits should work
    for num in 2 2 3 4 5 6 7 8 9 10
    do
       for file in `ls sorttemp | grep -E ^[[:digit:]]{$num}$`
       do
          sorttemp/$file
          touch sorttemp/0$file
       done
    done
    # strip 0s and print
    set `ls sorttemp`
    for val in $*
    do
       # too lazy to escape this and do it properly with perl -e
       echo '"'$val'" =~ /^0*(\d+)$/; print "$1\n";' > temp.pl
       perl temp.pl
    done
  • 05-19-2007 5:51 AM In reply to

    Re: Speed Challenge 0x10: Comparison

    Good work, everyone.
     
    asuffield's entry is the shortest one, and performs the task rather well, even with long lists. Only large numbers slow it down. It doesn't do negative numbers correctly, but at least it knows where to put the zero.
    Autonuke used a clever method in a surprising choice of language. And not only does it sort negative numbers, but it's also the fastest program wether you feed it large numbers or long lists.
    flop's program uses an interesting method to sort decimal as well as natural numbers. Unfortunately, it gobbles up any number of 0 and below, and takes forever to sort large numbers (and by large I mean 20). Nor does it put small numbers (0.000X) in the right order. And as a bonus, sometimes it just hangs.
    Unfortunately I was unable to run omega0's bash script, but I believe I got the gist of it. Very clever to use the file system to sort the numbers. But like assufield's entry, it incorrectly makes negative numbers positive.
     
    I must admit it was tempting to declare flop's entry the winner, but his enterprisey solution just has to take second place to Autonuke's smooth operator. Autonuke, you're next.
    rpar PROTON all
  • 05-19-2007 10:56 AM In reply to

    Re: Speed Challenge 0x10: Comparison

Page 1 of 1 (16 items)
Powered by Community Server (Non-Commercial Edition), by Telligent Systems