Created
May 14, 2013 22:21
-
-
Save sehe/5580146 to your computer and use it in GitHub Desktop.
t9
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iterator> | |
#include <iostream> | |
template <typename In, typename Out> | |
Out t9_transform(In f, In l, Out out) | |
{ | |
auto magic = [](decltype(*f) i) { return '2' + std::min(7, (i - (i >> 4)) / 3); }; | |
decltype(0+*f) previous = 0; | |
for(;f!=l;++f) { | |
if (*f>='a' && *f<='z') { | |
auto idx = *f - 'a'; | |
auto digit = magic(idx); | |
if (digit == previous) *out++ = ' '; | |
previous = digit; | |
static_assert(std::is_signed<decltype(idx)>::value, "difference type is required to be signed here"); | |
for (; idx>=0 && digit == magic(idx); --idx) | |
*out++ = digit; | |
} else | |
*out++ = '0'; | |
} | |
return out; | |
} | |
std::string t9(std::string const& input) | |
{ | |
std::string result; | |
// result.reserve(2*input.size()); | |
t9_transform(begin(input), end(input), std::back_inserter(result)); | |
return result; | |
} | |
int main() | |
{ | |
const std::string input = "abcdefghijklmnopqrstuvwxyz"; | |
auto output = t9_transform(begin(input), end(input), std::ostream_iterator<char>(std::cout)); | |
std::cout << std::endl << t9("hello world!") << std::endl; | |
// or, how about translating all of stdin to stdout, in streaming mode? | |
*t9_transform(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>(), output) = '\n'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When you find a variable named
magic
you know it's going to be interesting.Does the encoding function handle the 7 and 9 keys that have 4 characters well? I'll have to print out a map of char c to magic(c) to get an idea of why it works :)
The decltype(0+*f) expression is interesting…
About your last line, as I found out while doing the other CodeJam problem you can just specify an empty initialiser {} as the 2nd param, as the type is deduced from the first param, makes common istream_iterator usage like that shorter. In this case:
This at least works in Clang, not sure about other compilers.
BTW, why do you insist on the diff type to be signed?