|
15th Speed Challenge
Last post 05-19-2007 10:56 AM by Autonuke. 15 replies.
-
05-15-2007 8:20 AM
|
|
-
omega0


- Joined on 04-27-2007
- Posts 57
|
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.
|
|
-
-
Faxmachinen


- Joined on 03-19-2007
- Posts 199
|
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
|
|
-
-
omega0


- Joined on 04-27-2007
- Posts 57
|
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.
|
|
-
-
Faxmachinen


- Joined on 03-19-2007
- Posts 199
|
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
|
|
-
-
asuffield


- Joined on 05-31-2006
- Posts 2,137
|
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)
|
|
-
-
Autonuke


- Joined on 11-07-2006
- Posts 50
|
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].)
|
|
-
-
Autonuke


- Joined on 11-07-2006
- Posts 50
|
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).
|
|
-
-
flop


- 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".
|
|
-
-
asuffield


- Joined on 05-31-2006
- Posts 2,137
|
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.
|
|
-
-
flop


- 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.
|
|
-
-
Faxmachinen


- Joined on 03-19-2007
- Posts 199
|
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
|
|
-
-
flop


- 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.
|
|
-
-
omega0


- Joined on 04-27-2007
- Posts 57
|
Re: Speed Challenge 0x10: Comparison
edit - nvm, found an error and post delete doesn't work.
|
|
-
-
omega0


- Joined on 04-27-2007
- Posts 57
|
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
|
|
-
-
Faxmachinen


- Joined on 03-19-2007
- Posts 199
|
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
|
|
-
Page 1 of 1 (16 items)
|
|
|