Skip to content

Instantly share code, notes, and snippets.

@sehe
Created May 14, 2013 22:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sehe/5580146 to your computer and use it in GitHub Desktop.
Save sehe/5580146 to your computer and use it in GitHub Desktop.
t9
#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';
}
@zenmumbler
Copy link

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:

*t9_transform(std::istreambuf_iterator<char>(std::cin), {}, output) = '\n';

This at least works in Clang, not sure about other compilers.
BTW, why do you insist on the diff type to be signed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment