Ceylon, 1431, 764, 697, 571, 547, 538, 501, 493, 467, 451
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}
This was the original, ungolfed:
Integer footprintCharacter(Integer b) {
return sum({0, for(i in 0..7) if(b.get(i)) 1 });
}
Integer footPrintString(String s) {
if(s == "test") {return 0;}
return sum({0, for(c in s) footprintCharacter(c.integer)});
}
shared void footprint() {
if(exists s = process.arguments[0]) {
print(footPrintString(s));
} else {
print("This program needs at least one parameter!");
}
}
This takes the argument from a command line parameter ... process.arguments is an (possibly empty) sequence of strings, so before using one of them, we need to check if it actually exists. In the other case we output an error message (this is not required by the question and will be thrown away in the next versions).
Ceylon's sum
function takes a non-empty Iterable of elements of some type which needs to satisfy Summable
, i.e. has a plus
method, like Integer. (It doesn't work with empty sequences because each Summable type will have its own zero, and the runtime has no chance to know which one is meant.)
The elements of a string, or the one bits of an integer, are not a non-empty iterable. Therefore we are using here the feature to build an iterable by specifying some elements, then a "comprehension" (which will get evaluated to zero or more elements). So in the character case we are adding ones (but only when the corresponding bit is set), in the string case we are adding the result of the characters. (The comprehension will only be evaluated when the receiving function actually iterates over it, not when building the Iterable.)
Let's see how we can shrink this down. First, each of the functions is only called at one place, so we can inline them. Also, as mentioned above, get rid of the error message. (764 footprint points.)
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) sum({ 0, for (i in 0..7) if (c.integer.get(i)) 1 }) }));
}
}
}
We don't actually need the inner nested sum
, we can make this one big comprehension. (This saves us 37 footprint points for sum({0,})
, and some more for whitespace, which will be eliminated at the end anyways.) This is 697:
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
}
We can apply a similar principle to the special cased "test"
string: as in that case the result is 0 (i.e. nothing is contributed to the sum), we can just do this as a part of the summation (but we have to invert the condition). This mainly saves us the print(0);
, some braces and a bunch of indentation spaces, coming down to a footprint of 571:
shared void footprint() {
if (exists s = process.arguments[0]) {
print(sum({ 0, if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
We do the same for the first if
, with the side effect that now giving no argument also outputs 0
instead of doing nothing. (At least I thought that would happen here, instead it seems to hang with an eternal loop? Strange.)
shared void footprint() {
print(sum({ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
We can actually omit the ()
for the sum
function here, using an alternative function call syntax, which uses {...}
instead of ()
, and will fill in comprehensions into iterable arguments. This has footprint 538:
shared void footprint() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
Replacing the function name footprint
(40) by p
(3) saves another 37 points, bringing us to 501. (Ceylon function names have to start with lower case characters, so we can't get less than 3 points here.)
shared void p() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
The variable names s
(5) and c
(4), i
(4) are also not optimal. Let's replace them by a
(argument), d
(digit?) and b
(bit-index). Footprint 493:
shared void p() {
print(sum{ 0, if (exists a = process.arguments[0]) if (a != "test") for (c in a) for (b in 0..7) if (c.integer.get(b)) 1 });
}
I don't see any remaining non-whitespace optimization, so let's remove the non-needed whitespace (1 point for each space, two for each of the two line breaks):
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.integer.get(b))1});}
When browsing the API, I found that Character.hash actually returns the same value as its integer
attribute. But it has just 14 points instead of 30, so we come down to 451!
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}
When you said 'parameter', did you mean command line input or function argument or stdin? – Blue – 2015-09-25T11:18:45.033
36I'm sorry, I haven't been keeping up with the news, but I've just read it. Can we assume the German car company is definitely NOT called Volkswagen? – Level River St – 2015-09-25T11:18:47.600
@muddyfish either command line or stdin, up to you – Arnaud – 2015-09-25T11:20:45.350
Could you give some testcases? – Caridorc – 2015-09-25T11:51:05.860
7For reference, most costly to less costly characters:
\x7F}~_?{ow7yvu/s\x1F;=znm>k|OW[]^gc\x1Ex\x1D\eef\\'ZY+-VU.St\x173iNM5K6r\x0FG9:q<ljQ\x15\x13pC\aEF8IJL4\x0E21\x16RTh,X*)\x19\v&%\x1A#d\x1C\rab\
!"$(\x180\x05A\x14B\x12\x11DHP\x03\f\x06\n\t\x80\x10\x01@\x04\b\x02 \x00` – Caridorc – 2015-09-25T11:59:59.95719@steveverrill It is a fictional company, but its name indeed starts with V and has a W somewhere in the middle. But any similarities with reality is mere coincidence, least someone sues us. – Mindwin – 2015-09-25T12:40:16.650
@alexanderbird: see last sentence of the question - scoring is based on ecological footprint, not length – Jacob Krall – 2015-09-25T18:14:55.973
@JacobKrall - thanks, and oops. – alexanderbird – 2015-09-25T18:16:02.410
"Ecological Footprint" – PyRulez – 2015-09-25T19:56:31.057
1Functions allowed (instead of programs)? – Luis Mendo – 2015-09-25T20:58:11.730
1Hoping to see an x86 answer with
POPCNT
! – wchargin – 2015-09-26T06:19:10.797@Mindwin How about this for the company name: http://www.collinsdictionary.com/dictionary/german-english/verwackeln
– Level River St – 2015-09-26T20:52:12.980I will not embarass the company in question so I'll only tell you the initials: ~IBM~VW
– user45891 – 2015-09-27T10:32:48.71312They're lying to you! 1's are much more ecologically friendly than 0's. Want proof? Print out your source code in binary. 0's use nearly twice as much ink as 1's. And if you code with a dark background, they also waste more electricity to display on your screen. (If you code with a white background, you're already wasting electrons rendering all that white, so clearly any environmentally conscious programmer should be using a black background in their editor.) To be extra eco-friendly, we should all be writing in Whitespace... – Darrel Hoffman – 2015-09-27T18:03:56.090
1I actually have a concept for a language where the program would just be one character, but unfortunately I haven't made an interpreter yet. – DanTheMan – 2015-09-28T04:13:51.880
@DarrelHoffman that doesn't make sense with constantly backlit LCDs. – Ruslan – 2015-09-28T06:11:43.810