#include <stdio.h>
#include <string.h>
#include <malloc.h>

unsigned int shortRotCrazyPrint(unsigned int C, char goal);

//first character: b -> cause a jump to address 98 which will be encrypted first
// then execution continues with data pointer at 1 and program counter at 99

const char* translation = "5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72FhOA1CB6v^=I_0/8|jsb9m<.TVac`uY*MK'X~xDl}REokN:#?G\"i@";

unsigned int crazy(unsigned int a, unsigned int d){
    unsigned int crz[] = {1,0,0,1,0,2,2,2,1};
	int position = 0;
	unsigned int output = 0;
	while (position < 10){
		unsigned int i = a%3;
		unsigned int j = d%3;
		unsigned int out = crz[i+3*j];
		unsigned int multiple = 1;
		int k;
		for (k=0;k<position;k++)
			multiple *= 3;
		output += multiple*out;
		a /= 3;
		d /= 3;
		position++;
	}
	return output;
}

unsigned int rotateR(unsigned int d){
	unsigned int carry = d%3;
	d /= 3;
	d += 19683 * carry;
	return d;
}


unsigned int memory[59050]; // program
unsigned int memory_runtime[59050]; // memory at runtime: with encrypted commands
unsigned int lastAval = 0; // last value of A register

int main(int a, char* b[]){
	int outputCounter = 0;
	int i;
	unsigned char* out_s;
	int C;
	int firstIt;
	int stop;
	if (a > 1){
		int pos = 0;
		int sameLen = 0;
		for (i=1;i<a;i++){
			sameLen += strlen(b[i])+1;
		}
		if (sameLen == 0)
			sameLen++;
		out_s = (unsigned char*)(malloc(sameLen*sizeof(unsigned char)));
		for (i=1;i<a;i++){
			memcpy(out_s+pos,b[i],strlen(b[i]));
			pos+=strlen(b[i]);
			out_s[pos]=' ';
			pos++;
		}
		if (pos>0)
			pos--;
		out_s[pos]=0;
	}
	else{
		// READ STRING FROM STDIN
		// maximal 10.000 characters!
		int pos = 0;
		unsigned int result = 0;
		out_s = (unsigned char*)malloc(10001*sizeof(unsigned char));
		if (stdin == 0){
			printf("Cannot access STDIN.\n");
			return -1;
		}
		while (!feof(stdin) && pos < 10000){
			result = fread(out_s+pos,1,1,stdin);
			if (result<0){
				printf("Error while reading from STDIN.\n");
				return -1;
			}
			if (result==0)
				break;
			pos++;
		}
		out_s[pos]=0;
	}

	memory[0] = 'b'; //jmp to 99

	for (i=1;i<99;i++){
		int nop = (68-(i%94)+94)%94;
		if (nop<33) nop+=94;
		memory[i]=nop;
	}
	memcpy(memory_runtime,memory,99*sizeof(unsigned int));
	memory_runtime[98] = translation[memory[98]-33];
	C = 99;
	firstIt = 1;
	while (*out_s != 0){
		int inc;

		// if character is still in A register just print it out
		if (!firstIt){
			if (*out_s == *(out_s-1)){
				if (C+1 >= 59049){
					goto finish;
				}else{
					int out = (5-C%94+94)%94;
					if (out<33) out+=94;
					memory[C] = out;
					memory_runtime[C] = translation[out-33];
					C++;
					out_s++;
					continue;
				}
			}
		}

		// load character to A register
		do {
			C += (inc = shortRotCrazyPrint(C, *out_s));
			if (inc==0)
				out_s++;
		}while(inc == 0 && *out_s!=0);
		if (inc == 0)
			break;
		if (C+1 >= 59049){
			C-=inc;
			goto finish;
		}else{
			// print A register
			int out = (5-C%94+94)%94;
			if (out<33) out+=94;
			memory[C] = out;
			memory_runtime[C] = translation[out-33];
			C++;
		}
		firstIt = 0;
		out_s++;
	}

finish:
	while (C+1 >= 59049){
		C-=1;
	}
	// halt
	stop = (81-C%94+94)%94;
	if (stop<33) stop+=94;
	memory[C] = stop;
	memory_runtime[C] = translation[stop-33];
	C++;
	for (i=0;i<C;i++){
		printf("%c",(char)memory[i]);
	}
	printf("\n");

	return 0;
}



unsigned int shortRotCrazyPrint(unsigned int C, char goal) {
	int maxwidth = 1;
	int i;

	if (((unsigned char)goal >= 154 && (unsigned char)goal <= 208) || goal == 43)
		return 0; //TODO: 43 ('+') is possible with one shiftR and 2 crazies. At least a not-efficient + should be iplemented

	do{

		int rotPos = 0;
		int crazyInsteadRot = 0;

		if (maxwidth > 1000){
			// this should not occur
			return 0;
		}

		if (maxwidth + C >= 59049){
			//maximum space exceeded
			return 0;
		}

		do{
			unsigned int shift_val;
			unsigned int result;

			for (i=C;i<C+rotPos;i++){
				int nop = (68-i%94+94)%94;
				if (nop<33) nop+=94;
				memory[i]=nop;
				if (memory[i] >= 33 && memory[i] <= 126)
					if (i >= 98)
						memory_runtime[i] = translation[memory[i]-33];
					else
						memory_runtime[i] = memory[i];
			}

			if (!crazyInsteadRot){
				int shift = (39-(C+rotPos)%94+94)%94;
				if (shift<33) shift+=94;
				shift_val = memory_runtime[C+rotPos-98];

				memory[C+rotPos] = shift;
				if (C+rotPos >= 98)
					memory_runtime[C+rotPos] = translation[memory[C+rotPos]-33];
				else
					memory_runtime[C+rotPos] = memory[C+rotPos];
			}else{
				int cr = (62-(C+rotPos)%94+94)%94;
				if (cr<33) cr+=94;
				shift_val = memory_runtime[C+rotPos-98];

				memory[C+rotPos] = cr;
				if (C+rotPos >= 98)
					memory_runtime[C+rotPos] = translation[memory[C+rotPos]-33];
				else
					memory_runtime[C+rotPos] = memory[C+rotPos];
			}

			for (i=C+rotPos+1;i<(int)(C+maxwidth);i++){
				int nop = (68-i%94+94)%94;
				if (nop<33) nop+=94;
				memory[i]=nop;
				if (memory[i] >= 33 && memory[i] <= 126)
					if (i >= 98)
						memory_runtime[i] = translation[memory[i]-33];
					else
						memory_runtime[i] = memory[i];
			}


			if (rotPos + 1 < maxwidth){
				int crzy = (62-(C+maxwidth-1)%94+94)%94;
				unsigned int crzy_val = memory_runtime[C+maxwidth-1-98];
				if (crzy<33) crzy+=94;

				memory[C+maxwidth-1] = crzy;
				if (C+maxwidth-1 >= 98)
					memory_runtime[C+maxwidth-1] = translation[memory[C+maxwidth-1]-33];
				else
					memory_runtime[C+maxwidth-1] = memory[C+maxwidth-1];


				if (!crazyInsteadRot)
					result = crazy(rotateR(shift_val), crzy_val);
				else
					result = crazy(crazy(lastAval,shift_val), crzy_val);

			}else{
				if (!crazyInsteadRot)
					result = rotateR(shift_val);
				else
					result = crazy(lastAval,shift_val);
			}

			if ((unsigned char)result == (unsigned char)goal){
				//DONE!
				lastAval = result;
				return maxwidth;
			}

			if (crazyInsteadRot){
				rotPos++;
				crazyInsteadRot = 0;
			}else
				crazyInsteadRot = 1;
		}while (rotPos < maxwidth);

		maxwidth++;
	}while(1);

}