views:

766

answers:

9

Write the shortest program that calculates the Frobenius number for a given set of positive numbers. The Frobenius number is the largest number that cannot be written as a sum of positive multiples of the numbers in the set.

Example: For the set of the Chicken McNuggetTM sizes [6,9,20] the Frobenius number is 43, as there is no solution for the equation a*6 + b*9 + c*20 = 43 (with a,b,c >= 0), and 43 is the largest value with this property.

It can be assumed that a Frobenius number exists for the given set. If this is not the case (e.g. for [2,4]) no particular behaviour is expected.

References:

[Edit] I decided to accept the GolfScript version. While the MATHEMATICA version might be considered "technically correct", it would clearly take the fun out of the competition. That said, I'm also impressed by the other solutions, especially Ruby (which was very short for a general purpose language).

+3  A: 

Haskell 155 chars
The function f does the work and expects the list to be sorted. For example f [6,9,20] = 43

b x n=sequence$replicate n[0..x]
f a=last$filter(not.(flip elem)(map(sum.zipWith(*)a)(b u(length a))))[1..u] where
    h=head a
    l=last a
    u=h*l-h-l

P.S. since that's my first code golf submission I'm not sure how to handle input, what are the rules?

Daniel Velkov
KennyTM
That FAQ does not answer his question. It just says input format should be clearly stated by the code golf creator... and that's not even how the input is given...
Stephen
+1  A: 

Haskell 153 chars

A different take on a Haskell solution. I'm a rank novice at Haskell, so I'd be surprised if this couldn't be shortened.

m(x:a)(y:b)
 |x==y=x:m a b
 |x<y=x:m(y:b)a
 |True=y:m(x:a)b
f d=l!!s-1where
 l=0:foldl1 m[map(n+)l|n<-d]
 g=minimum d
 s=until(\n->l!!(n+g)-l!!n==g)(+1)0

Call it with, e.g., f [9,6,20].

Boojum
+4  A: 

GolfScript 47/42 chars

Faster solution (47).

~:+{0+{.1<{$}{1=}if|}/.!1):1\{:X}*+0=-X<}do];X(

Slow solution (42). Checks all values up to the product of every number in the set...

~:+{*}*{0+{.1<{$}{1=}if|}/1):1;}*]-1%.0?>,

Sample I/O:

$ echo "[6 9 20]"|golfscript frobenius.gs
43
$ echo "[60 90 2011]"|golfscript frobenius.gs
58349
Nabb
Arrgh. GolfScript should be permanently banned.
GeReV
+6  A: 

Mathematica 0 chars (or 19 chars counting the invoke command)

Invoke wtih

FrobeniusNumber[{a,b,c,...}]

Example

In[3]:= FrobeniusNumber[{6, 9, 20}]
Out[3]= 43

Is it a record? :)

belisarius
I'd call in 19 characters at least for the function name and brackets... :-(
Platinum Azure
@Platinum It's just the invoking code. If you decide to count it, you should count also (for example) the ´$ echo "[6 9 20]"|golfscript frobenius.gs´ in the previously posted GolfScript solution. Also note that the specification does not include an "input" spec.
belisarius
I just don't get how you can call it 0 characters when you *clearly had to type the function name with some number of keystrokes*. It makes absolutely no sense.
Platinum Azure
@Platinum The OP asks "Write the shortest program ...", and I didn´t need to write ANY program ... Anyway, I'll edit the title, just to get the matter settled.
belisarius
That's exactly it. You wrote no program, ergo your solution can't count. A program would presumably have the function invocation and some I/O routines.
Platinum Azure
This is at least 19 characters, but why so many downvotes? This answer is a great example of "Use the right programming language for the job".
ShreevatsaR
@ShreevatsaR: Some of us aren't willing to shell out $2500 to use this "right programming language".
Joey Adams
@ShreevatsaR: Again, this isn't an actual program. In the instructions, both for "What is code golf?" and this challenge, it specifically says you have to write a program. Having an interactive interpreter does NOT count. Since when could you simply open irb or interactive python and just enter "1+2+3+4+5+6+7+8+9+10" to solve the problem of "Find the sum of all numbers 1 to n"?
Platinum Azure
+2  A: 

Perl 105 107 110 119 122 127 152 158 characters

Latest edit: Compound assignment is good for you!

$h{0}=$t=1;$t*=$_ for@ARGV;for$x(1..$t){$h{$x}=grep$h{$x-$_},@ARGV}@b=grep!$h{$_},1..$t;print pop@b,"\n"

Explanation:

$t = 1;
$t *= $_ foreach(@ARGV);

Set $t to the product of all of the input numbers. This is our upper limit.

foreach $x (1..$t)
{
  $h{$x} = grep {$_ == $x || $h{$x-$_} } @ARGV;
}

For each number from 1 to $t: If it's one of the input numbers, mark it using the %h hash; otherwise, if there is a marked entry from further back (difference being anything in the input), mark this entry. All marked entries are non-candidates for Frobenius numbers.

@b=grep{!$h{$_}}(1..$t);

Extract all UNMARKED entries. These are Frobenius candidates...

print pop @b, "\n"

...and the last of these, the highest, is our Frobenius number.

Platinum Azure
+6  A: 

Ruby 100 86 80 chars

(newline not needed) Invoke with frob.rb 6 9 20

a=$*.map &:to_i;
p ((1..eval(a*"*")).map{|i|a<<i if(a&a.map{|v|i-v})[0];i}-a)[-1]

Works just like the Perl solution (except better:). $* is an array of command line strings; a is the same array as ints, which is then used to collect all the numbers which can be made; eval(a*"*") is the product, the max number to check.

In Ruby 1.9, you can save one additional character in by replacing "*" with ?*.

Edit: Shortened to 86 using Symbol#to_proc in $*.map, inlining m and shortening its calculation by folding the array.
Edit 2: Replaced .times with .map, traded .to_a for ;i.

AShelly
AShelly
@AShelly: `Symbol#to_proc` was added to Ruby 1.8 in 1.8.7.
Ventero
Time to upgrade, I guess.
AShelly
+2  A: 

Mathematica PROGRAM - 28 chars

Well, this is a REAL (unnecessary) program. As the other Mathematica entry shows clearly, you can compute the answer without writing a program ... but here it is

f[x__]:=FrobeniusNumber[{x}]

Invoke with

f[6, 9, 20]

43
belisarius
Ha! Negative votes seems to be contagious. However it still wins ...
belisarius
It doesn't happen to read input from stdin, does it?
Joey Adams
@Joey I don't see the stdin constrain in the specs. Is it a general code golf spec?
belisarius
@belisarius: As far as I know, yes, unless the programming language doesn't support it.
Joey Adams
A: 

FrobeniusScript 5 characters

solve

Sadly there does not yet exist any compiler/interpreter for this language.

No params, the interpreter will handle that:

$ echo solve > myProgram  
$ frobeniusScript myProgram
6
9
20
^D
Your answer is: 43
$ exit
Razor Storm
... No parms? :)
belisarius
It seems that there are people that play the anon boss game here. Why negative votes for a joke?
belisarius
I don't see anywhere in the rules that specified what language to use. This is perfectly within the scope of what's allowed, and is currently the winner. ;) What's with the downvote? If you think joke entries are dumb fine, here's my rebuttle: This is a satirical commentary on how flawed language ambiguous code golf is. Knowing how to program in some esoteric language designed for terse syntax (ahem golfscript) should not qualify you as a more innovative code artist. (I don't say programmer because anyone who actually programs like this should get shot :])
Razor Storm
The reason I downvoted was that someone does this EVERY code golf. It was funny and poignant when Jon Skeet did it but now it's a bit tired. It's not like you lost rep.
Ron Warholic
I'm not angry at rep, frankly it's a bit flawed system that causes tension and popularity contests, also, I have never read any of the other code golfs. I wasn't trying to be cliche, but I can see how it would get annoying after a while. However, shouldn't that just be more reason for a design change in the code golf? Surely as programmers we can't just assume people would abide by the spirit of the rules and instead should be catching all kinds of exploits with the design of the contest. :) That allows for much cleaner contest and less confusion/miscommunication/stupid people like me. :P
Razor Storm
There are things that can only be done once ... after that it's just a boring copy of something that someone else did before.
HoLyVieR
@HoLyVieR actually, purely as a joke, this is not even funny the first time. You can't call someone a humorous visionary for simply being lucky enough to post this joke first. This isn't even anything revolutionary, anyone would have, (and has) thought of this.
Razor Storm
A: 

C#, 360 characters

using System;using System.Linq;class a{static void Main(string[]b)
{var c=(b.Select(d=>int.Parse(d))).ToArray();int e=c[0]*c[1];a:--e;
var f=c.Length;var g=new int[f];g[f-1]=1;int h=1;for(;;){int i=0;for
(int j=0;j<f;j++)i+=c[j]*g[j];if(i==e){goto a;}if(i<e){g[f-1]++;h=1;}
else{if(h>=f){Console.Write(e);return;}for(int k=f-1;k>=f-h;k--)
g[k]=0;g[f-h-1]++;h++;}}}}

I'm sure there's a shorter C# solution than this, but this is what I came up with.

This is a complete program that takes the values as command-line parameters and outputs the result to the screen.

Jeffrey L Whitledge
Woah, I have *no* idea what this code does. I got lost at the `a:--e` line... and then later you somehow `goto a`, which is... a... class... meep.
Stephen
@Stephen `a:` is a label, `goto a` jumps to that label. `a:--e` is just `a:` and `--e;` without whitespace between them.
Jamie Penney
Oh. Duh. Wasn't thinking - just got very confused because he called the class 'a' as well. Thought it was some funky C# stuff.
Stephen
@Stephen - Yeah, in C# labels are in their own namespace. Since a label is the only thing that can appear before a colon or after a goto (except in the case of a switch statement), there is no trouble re-using identifiers for them. I just named everything in alphabetical order, and thought it would be fun to reuse the class name there. I'm glad that got the reaction I wanted! :-D
Jeffrey L Whitledge