#!/bin/sh
grep -e "g\(()\)*('al')" $0 | sed 's/()/o/g' | sed "s/('al')/al/"
exit
g()('al')
On its own, g()('al') is valid but g()()('al') is a syntax error. Also, bash and sh don't have non-numeric return values, so regardless of the solution you're stuck with printing.
Just to clarify, I think it's a non-solution because the g()('al') is never actually executed - grep does all the work. You can add as many parenthesis as you want. The "exit" is there because you'll get a syntax error if you try to execute g()()('al'). g()('al') by itself does nothing (I'm not even sure why it's not flagged as a syntax error).
The three people who are judging this had a long discussion over this case, and basically decided that since it is in the file, it's fine. We frown on it a little because it's basically self-modifying code, but it's better than nothing for bash.
Here's my C# solution that uses no global state, and features a cool (I think) variadic lambda.
using System;
using System.Linq;
class Program {
static void Main() {
Console.WriteLine(g("al"));
Console.WriteLine(g()("al"));
Console.WriteLine(g()()("al"));
Console.WriteLine(g()()()("al"));
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
delegate dynamic Goal(params string[] args);
static dynamic g(string suffix = null, string prefix = "g") {
if (suffix == "al") return prefix + suffix;
return (Goal)(a => g(a.FirstOrDefault(), prefix + "o"));
}
}
It was a fun exercise. I found that creating a github pull request was not such a fun exercise, and took about 10x longer than the actual task at hand. Perhaps I could learn to do it more smoothly with practice.
I made this Go one that might be cheating because instead of the ("al") call returning a string, you get a value that implements the String method. Works with fmt.Println :)
as the last line of solution 1, the assertion will not pass. I'm not saying there is a rule that mentions "resetting state". I'm saying that their failure to reset state is the bug leading to them not following the rules.
That helps but doesn't completely solve the state problem. Try adding these two lines to the end of the program:
g()()()()()
print g('al')
I think 'gal' should be printed here. Rule 7 says that's what your function should return given 'al', and the fact that we've called it in some other way before doesn't change the fact that it is required to return 'gal' given 'al'.
The solution I posted above handles this scenario (and, as a bonus, is thus threadsafe in case multiple people were doing g()()()('al') simultaneously).
# goal.rb
module G
def [](o=nil)
o ? "g#{values[0].to_s}al" : ({ :n => values[0].to_s + "o" }.extend G)
end
end
g = {}.extend G
eval DATA.read.gsub("(", "[").gsub(")", "]")
__END__
gal = g('al')
p gal
goal = g()('al')
p goal
goooooooal = g()()()()()()()('al')
p goooooooal
# ruby goal.rb
# "gal"
# "goal"
# "goooooooal"
The table at the bottom is interesting. I'd love to read articles about why it's impossible in language X. E.g. I'm familiar with C/Python and can implement a solution, and am surprised that it'd be impossible in Ruby - I don't know Ruby, and would love to know why.
More generally, what properties must a programming language satisfy for this problem to be solvable in it?
My current intuition is that if a language does not denote function calls with () enclosing arguments, AND if a language does not support metaprogramming (eg. LISP macros), then the problem is not solvable in it. Still thinking about it.
Ruby and Java both lack first class functions--functions can't return values that can be directly called with () (unless this has changed with Java 8?).
Ugh, so many solutions that mutate internal state. I went for a more purely functional approach and kept track of the count with a function parameter (JavaScript):
function g(o)
if o then return "gal" end
o = "o"
local function go(al)
if al then
return "g"..o..al
else
o = o .. "o"
return go
end
end
return go
end
print(g()('al'))
More amusing and hackish solution:
setmetatable(_G, -- or _ENV, but maintain 5.1 compatibility
{ __index = function(_, g)
local o = ""
local function go(al)
if al then
return g..o..al
end
o = o.."o"
return go
end
return go
end})
print(g()('al'))
print(G()'al')
print(Wh()()'pdedo')
a straightfoward translation of the Javascript version w/ closures should work
function goal(n)
return function(al)
if al then
return "G" .. string.rep("o", n) .. al
else
return goal(n+1)
end
end
end
G = goal(0)
print( G()()('al') )
Also note that G()'al' is just syntactic sugar for G()('al') in Lua