Just for exercise, if people want to give it a go; see how creative one can be.

Problem Statement: Given a list of data from a file( or user input which ever) as such:

``````char 1
char 2
char 26
char 27
char 52
char 53``````

output the mapping of the number like so:

``````char 1 => 'a'
char 2 => 'b'
char 26 = 'z'
char 27 => 'A'
char 52 => 'Z'
char 53 => 'aa'``````

If you don't see the pattern then here it is:

``````[1...26] gets mapped to ['a'...'z']
[27...52] gets mapped to ['A'...'Z']``````

any thing after 52, ex 53 gets wrapped back. For example 53 gets wrapped to 'aa' or 54 gets wrapped to 'bb' or 79 gets wrapped to 'AA'
Free to use any language paradigm....blah...blah...blah, just make sure its understandable.

Difficulty: 2.0f/5.0f

m4ster_r0shi commented: Make more threads like this one! +7

make a simple array container add 2 functios such as add() and operator[]
witch knows the number ranges :)

Something along the lines of:

``````string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
string input;
getline(cin,input);
stringstream ss(input);
unsigned int value = 0;
ss >> value;
if(value <= 0)
{
cerr << "Program encountered an unexpected error and will now exit. (Mwuahahaha!)" << endl;
return 1;
}
cout << "value = " << value << endl;

//j is the current index into "alphabet"
//r is the number of times it has wrapped around.
//i is simply used by the loop as the "loop-control" variable.
string::size_type i = 0, j = 0, r = 0;
for( ; i < value; i++, j++)
{
if(j == alphabet.size()) { j = 0; r++; }
}

string output;
for( string::size_type k = 0; k < (r+1); k++ )
{
output += alphabet[j-1];
}
cout << "Output = " << output << endl;``````

Or maybe something along the lines of:

``````#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
ifstream infile("input.txt");
ofstream outfile("output.txt");
int value;
while(infile >> value) {
char mod_val = (--value) % 52;
outfile << string(value / 52 + 1,
(mod_val < 26 ? mod_val + 'a' : (mod_val - 26) + 'A'))
<< endl;
};
return 0;
};``````

Or maybe something along the lines of:

``````#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
ifstream infile("input.txt");
ofstream outfile("output.txt");
int value;
while(infile >> value) {
char mod_val = (--value) % 52;
outfile << string(value / 52 + 1,
(mod_val < 26 ? mod_val + 'a' : (mod_val - 26) + 'A'))
<< endl;
};
return 0;
};``````

The only problem being the assumption of adjacent letters in the character set. Only digits are guaranteed to be contiguous. But great minds think alike, because my solution is different from yours only in that I used a custom alphabet:

``````#include <type_traits>

namespace jsw {
/**
* @brief Subtract y from x
* @remarks Moves in an absolute negative direction while preserving sign
*/
template <typename T>
T subtract(T x, T y, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
{
return (x >= 0) ? x - y : x + y;
}

/**
* @brief Calculates the remainder of x / y
* @remarks Behavior is sign agnostic (equivalent regardless of sign)
*/
template <typename T>
T mod(T x, T y, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
{
return (x % y + y) % y;
}
}

#include <cstdlib>
#include <iostream>
#include <string>

int main()
{
std::string const buf = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int value;

while (std::cin >> value) {
value = jsw::subtract(value, 1);

int const n_wrap = std::abs(value) / buf.size() + 1;
int const index = jsw::mod(value, (int)buf.size());

std::cout << std::string(n_wrap, buf[index]) << '\n';
}
}``````

Yeah now I'm depressed I didn't do the modulus thing. I was thinking about it I swear!

This isn't much of a challenge as it is now, so I decided to do the interesting stuff during compilation.

EDIT: A boost preprocessor array can't have more than 25 elements. That's why I had to split the letters like that.

``````#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/arithmetic/div.hpp>
#include <boost/preprocessor/arithmetic/mod.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/array/elem.hpp>
#include <boost/preprocessor/control/if.hpp>

#define LETTERS_a_m (13, ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"))
#define LETTERS_n_z (13, ("n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"))
#define LETTERS_A_M (13, ("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"))
#define LETTERS_N_Z (13, ("N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"))

#define LETTER_LOWER(n) \
BOOST_PP_IF(BOOST_PP_LESS(n, 13), \
BOOST_PP_ARRAY_ELEM(n, LETTERS_a_m), \
BOOST_PP_ARRAY_ELEM(BOOST_PP_SUB(n, 13), LETTERS_n_z))

#define LETTER_UPPER(n) \
BOOST_PP_IF(BOOST_PP_LESS(n, 13), \
BOOST_PP_ARRAY_ELEM(n, LETTERS_A_M), \
BOOST_PP_ARRAY_ELEM(BOOST_PP_SUB(n, 13), LETTERS_N_Z))

#define LETTER(z, n, letter_id) \
BOOST_PP_IF(BOOST_PP_LESS(letter_id, 27), \
LETTER_LOWER(BOOST_PP_SUB(letter_id, 1)), \
LETTER_UPPER(BOOST_PP_SUB(letter_id, 27)))

#define PRINT_LETTER(r, unused, n) \
BOOST_PP_REPEAT(BOOST_PP_ADD(BOOST_PP_DIV(n, 52), 1), LETTER, BOOST_PP_MOD(n, 52)) "\n"

#include <cstdio>

#define INPUT (1)(2)(4)(8)(16)(32)(50)(64)(100)(128)(150)

int main()
{
const char * output = BOOST_PP_SEQ_FOR_EACH(PRINT_LETTER, ~, INPUT);

printf(output);
fflush(stdout);

return 0;
}``````

Compiler output:

``````.file	"main.cpp"
.def	___main;	.scl	2;	.type	32;	.endef
.section .rdata,"dr"
LC0:
.ascii [B]"a\12b\12d\12h\12p\12F\12X\12ll\12VV\12xxx\12TTT\0"[/B]
.text
.globl _main
.def	_main;	.scl	2;	.type	32;	.endef
_main:
pushl	%ebp
movl	%esp, %ebp
andl	\$-16, %esp
subl	\$16, %esp
call	___main
movl	\$LC0, (%esp)
call	_puts
movl	__imp___iob, %eax
movl	%eax, (%esp)
call	_fflush
xorl	%eax, %eax
leave
ret
.def	_puts;	.scl	2;	.type	32;	.endef
.def	_fflush;	.scl	2;	.type	32;	.endef``````
commented: show off +13

This isn't much of a challenge as it is now, so I decided to do the interesting stuff during compilation.

EDIT: A boost preprocessor array can't have more than 25 elements. That's why I had to split the letters like that.

``````#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/arithmetic/div.hpp>
#include <boost/preprocessor/arithmetic/mod.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/array/elem.hpp>
#include <boost/preprocessor/control/if.hpp>

#define LETTERS_a_m (13, ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"))
#define LETTERS_n_z (13, ("n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"))
#define LETTERS_A_M (13, ("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"))
#define LETTERS_N_Z (13, ("N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"))

#define LETTER_LOWER(n) \
BOOST_PP_IF(BOOST_PP_LESS(n, 13), \
BOOST_PP_ARRAY_ELEM(n, LETTERS_a_m), \
BOOST_PP_ARRAY_ELEM(BOOST_PP_SUB(n, 13), LETTERS_n_z))

#define LETTER_UPPER(n) \
BOOST_PP_IF(BOOST_PP_LESS(n, 13), \
BOOST_PP_ARRAY_ELEM(n, LETTERS_A_M), \
BOOST_PP_ARRAY_ELEM(BOOST_PP_SUB(n, 13), LETTERS_N_Z))

#define LETTER(z, n, letter_id) \
BOOST_PP_IF(BOOST_PP_LESS(letter_id, 27), \
LETTER_LOWER(BOOST_PP_SUB(letter_id, 1)), \
LETTER_UPPER(BOOST_PP_SUB(letter_id, 27)))

#define PRINT_LETTER(r, unused, n) \
BOOST_PP_REPEAT(BOOST_PP_ADD(BOOST_PP_DIV(n, 52), 1), LETTER, BOOST_PP_MOD(n, 52)) "\n"

#include <cstdio>

#define INPUT (1)(2)(4)(8)(16)(32)(50)(64)(100)(128)(150)

int main()
{
const char * output = BOOST_PP_SEQ_FOR_EACH(PRINT_LETTER, ~, INPUT);

printf(output);
fflush(stdout);

return 0;
}``````

Compiler output:

``````.file	"main.cpp"
.def	___main;	.scl	2;	.type	32;	.endef
.section .rdata,"dr"
LC0:
.ascii [B]"a\12b\12d\12h\12p\12F\12X\12ll\12VV\12xxx\12TTT\0"[/B]
.text
.globl _main
.def	_main;	.scl	2;	.type	32;	.endef
_main:
pushl	%ebp
movl	%esp, %ebp
andl	\$-16, %esp
subl	\$16, %esp
call	___main
movl	\$LC0, (%esp)
call	_puts
movl	__imp___iob, %eax
movl	%eax, (%esp)
call	_fflush
xorl	%eax, %eax
leave
ret
.def	_puts;	.scl	2;	.type	32;	.endef
.def	_fflush;	.scl	2;	.type	32;	.endef``````

Thats so not fair, I still have no complete idea what the hell is going on. Mainly because I never gave enough time to learn metaprogramming and boost metaprogramming. Anyways I'll take your word for it to work. Thats pretty cool.

Thats pretty cool.

Haha, thanks! :D

There is a bug in the code above though... It won't work for some edge cases
(e.g. 52 is mapped to "aa" (as is 53) instead of "Z"). I realised it too late to edit
it and correct it (BTW, what's this thing with the 30 minute limit to editing? Why
can't I edit my posts whenever I want?). `PRINT_LETTER` should look like this:

``````#define PRINT_LETTER(r, unused, n) \
LETTER, BOOST_PP_ADD(BOOST_PP_MOD(BOOST_PP_SUB(n, 1), 52), 1)) "\n"``````

I never gave enough time to learn metaprogramming

In this case, I think I'll seize the opportunity to show off a little bit more :P

I'll do the same thing using just template metaprogramming (no boost preprocessor tricks). Note that the end
result won't be the same. What I got using preprocessor metaprogramming was a literal constant just the way
I wanted it. I can't do that using just template metaprogramming (AFAIK). The best I can do in this case is fill an
existing array with values generated during compilation. The filling itself will still be made while the program runs.

Let's begin with something simple. A template that generates code that prints the numbers 0 ... 9.

``````#include <cstdio>

template <int MAX_I, int CUR_I = 0>
struct PrintLoop
{
static void RUN()
{
printf("%c\n", CUR_I + '0');

PrintLoop<MAX_I, CUR_I + 1>::RUN();
}
};

template <int MAX_I>
struct PrintLoop<MAX_I, MAX_I>
{
static void RUN() {}
};

int main()
{
PrintLoop<10>::RUN();

fflush(stdout);
}``````

Compiler output (note that I compile everything using -Os (code size optimization)):

``````.file	"main.cpp"
.def	___main;	.scl	2;	.type	32;	.endef
.section .rdata,"dr"
LC0:
.ascii "%c\12\0"
.text
.globl _main
.def	_main;	.scl	2;	.type	32;	.endef
_main:
pushl	%ebp
movl	%esp, %ebp
andl	\$-16, %esp
subl	\$16, %esp
call	___main
movl	\$48, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$49, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$50, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$51, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$52, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$53, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$54, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$55, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$56, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	\$57, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	__imp___iob, %eax
movl	%eax, (%esp)
call	_fflush
xorl	%eax, %eax
leave
ret
.def	_printf;	.scl	2;	.type	32;	.endef
.def	_fflush;	.scl	2;	.type	32;	.endef``````

It's good, but not good enough. There's something I don't like. There are too many printf calls. Let's see if I can do better...

``````#include <cstdio>

char output[100] = { 0 };
int output_index = 0;

template <int MAX_I, int CUR_I = 0>
struct FillBufferLoop
{
static void RUN()
{
output[output_index++] = CUR_I + '0';
output[output_index++] = '\n';

FillBufferLoop<MAX_I, CUR_I + 1>::RUN();
}
};

template <int MAX_I>
struct FillBufferLoop<MAX_I, MAX_I>
{
static void RUN() {}
};

int main()
{
FillBufferLoop<10>::RUN();

printf("%s", output);
fflush(stdout);
}``````

Compiler output:

``````.file	"main.cpp"
.def	___main;	.scl	2;	.type	32;	.endef
.section .rdata,"dr"
LC0:
.ascii "%s\0"
.text
.globl _main
.def	_main;	.scl	2;	.type	32;	.endef
_main:
pushl	%ebp
movl	%esp, %ebp
andl	\$-16, %esp
subl	\$16, %esp
call	___main
movl	_output_index, %eax
movb	\$48, _output(%eax)
movb	\$10, _output+1(%eax)
movb	\$49, _output+2(%eax)
movb	\$10, _output+3(%eax)
movb	\$50, _output+4(%eax)
movb	\$10, _output+5(%eax)
movb	\$51, _output+6(%eax)
movb	\$10, _output+7(%eax)
movb	\$52, _output+8(%eax)
movb	\$10, _output+9(%eax)
movb	\$53, _output+10(%eax)
movb	\$10, _output+11(%eax)
movb	\$54, _output+12(%eax)
movb	\$10, _output+13(%eax)
movb	\$55, _output+14(%eax)
movb	\$10, _output+15(%eax)
movb	\$56, _output+16(%eax)
movb	\$10, _output+17(%eax)
movb	\$57, _output+18(%eax)
movb	\$10, _output+19(%eax)
movl	%eax, _output_index
movl	\$_output, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	__imp___iob, %eax
movl	%eax, (%esp)
call	_fflush
xorl	%eax, %eax
leave
ret
.globl _output
.bss
.align 4
_output:
.space 100
.globl _output_index
.align 4
_output_index:
.space 4
.def	_printf;	.scl	2;	.type	32;	.endef
.def	_fflush;	.scl	2;	.type	32;	.endef``````

Yeap, that's more like it. Now, let's see how this can be applied to the problem at hand.

I'll need two loops for this. An outer one, that will iterate over the input
data, and an inner one, that will generate the string mapped to the current
integer. Also, note that neither the int -> letter mapping nor the input data
can be arrays if I want to be able to use them as template arguments (AFAIK).

``````#include <cstdio>

template <int N>
struct Letters;

#define DEF_LETTER(index, value) \
template <> struct Letters<index> \
{ static const char VAL = value; };

DEF_LETTER( 0, 'a') DEF_LETTER( 1, 'b') DEF_LETTER( 2, 'c') DEF_LETTER( 3, 'd')
DEF_LETTER( 4, 'e') DEF_LETTER( 5, 'f') DEF_LETTER( 6, 'g') DEF_LETTER( 7, 'h')
DEF_LETTER( 8, 'i') DEF_LETTER( 9, 'j') DEF_LETTER(10, 'k') DEF_LETTER(11, 'l')
DEF_LETTER(12, 'm') DEF_LETTER(13, 'n') DEF_LETTER(14, 'o') DEF_LETTER(15, 'p')
DEF_LETTER(16, 'q') DEF_LETTER(17, 'r') DEF_LETTER(18, 's') DEF_LETTER(19, 't')
DEF_LETTER(20, 'u') DEF_LETTER(21, 'v') DEF_LETTER(22, 'w') DEF_LETTER(23, 'x')
DEF_LETTER(24, 'y') DEF_LETTER(25, 'z') DEF_LETTER(26, 'A') DEF_LETTER(27, 'B')
DEF_LETTER(28, 'C') DEF_LETTER(29, 'D') DEF_LETTER(30, 'E') DEF_LETTER(31, 'F')
DEF_LETTER(32, 'G') DEF_LETTER(33, 'H') DEF_LETTER(34, 'I') DEF_LETTER(35, 'J')
DEF_LETTER(36, 'K') DEF_LETTER(37, 'L') DEF_LETTER(38, 'M') DEF_LETTER(39, 'N')
DEF_LETTER(40, 'O') DEF_LETTER(41, 'P') DEF_LETTER(42, 'Q') DEF_LETTER(43, 'R')
DEF_LETTER(44, 'S') DEF_LETTER(45, 'T') DEF_LETTER(46, 'U') DEF_LETTER(47, 'V')
DEF_LETTER(48, 'W') DEF_LETTER(49, 'X') DEF_LETTER(50, 'Y') DEF_LETTER(51, 'Z')

template <int N>
struct Input;

#define DEF_INPUT(index, value) \
template <> struct Input<index> \
{ static const int VAL = value; };

const int input_size = 15;

DEF_INPUT( 0,  1) DEF_INPUT( 1,   3) DEF_INPUT( 2,  25) DEF_INPUT( 3,  26) DEF_INPUT( 4,  27)
DEF_INPUT( 5, 30) DEF_INPUT( 6,  51) DEF_INPUT( 7,  52) DEF_INPUT( 8,  53) DEF_INPUT( 9,  59)
DEF_INPUT(10, 80) DEF_INPUT(11, 103) DEF_INPUT(12, 104) DEF_INPUT(13, 105) DEF_INPUT(14, 110)

const int output_size = 100;

char output[output_size] = { 0 };

int output_index = 0;

template <char CUR_C, int MAX_I, int CUR_I = 0>
struct InnerLoop
{
static void RUN()
{
output[output_index++] = CUR_C;

InnerLoop<CUR_C, MAX_I, CUR_I + 1>::RUN();
}
};

template <char CUR_C, int MAX_I>
struct InnerLoop<CUR_C, MAX_I, MAX_I>
{
static void RUN() {}
};

template <int MAX_I, int CUR_I = 0>
struct OuterLoop
{
static void RUN()
{
InnerLoop<Letters<(Input<CUR_I>::VAL - 1) % 52 >::VAL, (Input<CUR_I>::VAL - 1) / 52 + 1>::RUN();

output[output_index++] = '\n';

OuterLoop<MAX_I, CUR_I + 1>::RUN();
}
};

template <int MAX_I>
struct OuterLoop<MAX_I, MAX_I>
{
static void RUN() {}
};

int main()
{
OuterLoop<input_size>::RUN();

printf("%s", output);
fflush(stdout);
}``````

Compiler output:

``````.file	"main.cpp"
.def	___main;	.scl	2;	.type	32;	.endef
.section .rdata,"dr"
LC0:
.ascii "%s\0"
.text
.globl _main
.def	_main;	.scl	2;	.type	32;	.endef
_main:
pushl	%ebp
movl	%esp, %ebp
andl	\$-16, %esp
subl	\$16, %esp
call	___main
movl	_output_index, %eax
movb	\$97, _output(%eax)
movb	\$10, _output+1(%eax)
movb	\$99, _output+2(%eax)
movb	\$10, _output+3(%eax)
movb	\$121, _output+4(%eax)
movb	\$10, _output+5(%eax)
movb	\$122, _output+6(%eax)
movb	\$10, _output+7(%eax)
movb	\$65, _output+8(%eax)
movb	\$10, _output+9(%eax)
movb	\$68, _output+10(%eax)
movb	\$10, _output+11(%eax)
movb	\$89, _output+12(%eax)
movb	\$10, _output+13(%eax)
movb	\$90, _output+14(%eax)
movb	\$10, _output+15(%eax)
movb	\$97, _output+16(%eax)
movb	\$97, _output+17(%eax)
movb	\$10, _output+18(%eax)
movb	\$103, _output+19(%eax)
movb	\$103, _output+20(%eax)
movb	\$10, _output+21(%eax)
movb	\$66, _output+22(%eax)
movb	\$66, _output+23(%eax)
movb	\$10, _output+24(%eax)
movb	\$89, _output+25(%eax)
movb	\$89, _output+26(%eax)
movb	\$10, _output+27(%eax)
movb	\$90, _output+28(%eax)
movb	\$90, _output+29(%eax)
movb	\$10, _output+30(%eax)
movb	\$97, _output+31(%eax)
movb	\$97, _output+32(%eax)
movb	\$97, _output+33(%eax)
movb	\$10, _output+34(%eax)
movb	\$102, _output+35(%eax)
movb	\$102, _output+36(%eax)
movb	\$102, _output+37(%eax)
movb	\$10, _output+38(%eax)
movl	%eax, _output_index
movl	\$_output, 4(%esp)
movl	\$LC0, (%esp)
call	_printf
movl	__imp___iob, %eax
movl	%eax, (%esp)
call	_fflush
xorl	%eax, %eax
leave
ret
.globl _output
.bss
.align 4
_output:
.space 100
.globl _output_index
.align 4
_output_index:
.space 4
.def	_printf;	.scl	2;	.type	32;	.endef
.def	_fflush;	.scl	2;	.type	32;	.endef``````

Program output:

``````a
c
y
z
A
D
Y
Z
aa
gg
BB
YY
ZZ
aaa
fff``````

Well, while m4ster_r0shi is going at it, I might flex my C++ muscles too...

I just wanted to make the point that doing things at compile-time with meta-programming techniques doesn't have to be really complex and elaborate like m4ster_r0shi's example, especially with C++0x support. For this problem, you could simply do:

``````#include <iostream>
#include <string>

const char alphabet[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

template <unsigned int Size, unsigned int Index>
struct decoding {
static constexpr std::string value(const int (&arr)[Size]) {
return std::string( (arr[Index] - 1) / 52 + 1,
alphabet[(arr[Index] - 1) % 52] )
+ "\n"
+ decoding<Size, Index + 1>::value(arr);
};
};

template <unsigned int Size>
struct decoding<Size, Size> {
static constexpr std::string value(const int (&)[Size]) {
return "";
};
};

template <unsigned int Size>
constexpr std::string decode(const int (&arr)[Size]) { return decoding< Size, 0 >::value(arr); };

int main() {
constexpr int input[] = {1, 3, 25, 26, 27, 30, 51, 52, 53, 59, 80, 103, 104, 105, 110};

std::cout << decode(input) << std::endl;

return 0;
};``````

Damn. I really have to start to familiarize myself with the upcoming standard.

Are we in the assembly forums or something?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.