Finish c_impl of problem solution

This commit is contained in:
Stephen Seo 2021-08-18 16:43:55 +09:00
parent 449ad303f1
commit 1fdf5e14b7
3 changed files with 449 additions and 245 deletions

View file

@ -14,7 +14,6 @@ void printHelp() {
}
typedef struct Sequence {
unsigned long long idx;
unsigned char *buf;
size_t buf_size;
size_t buf_end;
@ -39,35 +38,48 @@ void doubleIndBuf(Sequence *seq) {
seq->indices_size *= 2;
}
void nextSeqItem(Sequence *seq) {
if(seq->buf_end > seq->buf_size) {
puts("ERROR: Sequence in invalid state!");
return;
} else if(seq->buf_end == seq->buf_size) {
doubleSeqBuf(seq);
int nextSeqItem(Sequence *seq) {
if(seq->indices[seq->indices_end] == 0) {
size_t idx = seq->indices[seq->indices_end - 1] + 1;
for(; idx < seq->buf_size && seq->buf[idx] != 0; ++idx) {
if(seq->buf[idx] == 't' || seq->buf[idx] == 'T') {
break;
}
}
if(seq->buf[idx] != 't' && seq->buf[idx] != 'T') {
puts("ERROR: Invalid state!");
return 1;
}
seq->indices[seq->indices_end++] = idx;
const char *next_str = numberToString(idx + 1);
size_t next_str_size = strlen(next_str);
while(seq->buf_end + next_str_size + 1 >= seq->buf_size) {
doubleSeqBuf(seq);
}
memcpy(seq->buf + seq->buf_end, next_str, next_str_size);
seq->buf_end += next_str_size;
free((void*)next_str);
}
if(seq->buf_end == 0 || seq->indices_end == 0) {
puts("ERROR: Sequence is zero sized, this should not be possible!");
return;
}
return 0;
}
Sequence initSequence() {
Sequence seq;
seq.idx = 0;
seq.buf = calloc(INIT_SEQ_BUF_SIZE, 1);
seq.buf_size = INIT_SEQ_BUF_SIZE;
seq.buf_end = 0;
seq.indices = malloc(sizeof(unsigned long long) * INIT_SEQ_IND_SIZE);
seq.indices = calloc(sizeof(unsigned long long), INIT_SEQ_IND_SIZE);
seq.indices_size = INIT_SEQ_IND_SIZE;
// seq.indices_end = 0; initialized later on
while(seq.indices_size < 3) {
doubleIndBuf(&seq);
}
seq.indices[0] = 1;
seq.indices[1] = 4;
seq.indices[2] = 11;
seq.indices[0] = 0;
seq.indices[1] = 3;
seq.indices[2] = 10;
seq.indices_end = 3;
size_t startingLength = strlen(STARTING_SEQ);
@ -119,5 +131,22 @@ int main(int argc, char **argv) {
printf("Got input count == %llu\n", count);
// const char *nString = numberToString(count);
// printf("Test string of number is %s\n", nString);
// free((void*)nString);
Sequence seq = initSequence();
while(seq.indices_end < count) {
nextSeqItem(&seq);
}
printf("String is %s\n", seq.buf);
for(size_t i = 0; i < seq.indices_end; ++i) {
printf("%llu ", seq.indices[i] + 1);
}
puts("");
cleanupSequence(&seq);
return 0;
}

View file

@ -1,5 +1,7 @@
#include "numberToString.h"
#include <stdio.h>
void doubleBufSize(char **buf, size_t *buf_size) {
char *newBuf = calloc(2, *buf_size);
memcpy(newBuf, *buf, *buf_size);
@ -8,249 +10,394 @@ void doubleBufSize(char **buf, size_t *buf_size) {
*buf_size *= 2;
}
// TODO logic is convoluted here
void thousandToString(char **buf, size_t *buf_idx, size_t *buf_size, unsigned long long t, int last) {
t = t % 1000;
if(t == 0) {
return;
NumToken * doubleTokensBuf(NumToken *tokens, size_t *tokens_size) {
NumToken *newTokens = calloc(sizeof(NumToken), *tokens_size * 2);
memcpy(newTokens + *tokens_size, tokens, sizeof(NumToken) * *tokens_size);
free(tokens);
*tokens_size *= 2;
return newTokens;
}
NumToken * numberToTokens(unsigned long long n, size_t *tokens_size_out) {
size_t tokens_size = INIT_SEQ_NUM_TOKENS_SIZE;
*tokens_size_out = tokens_size;
NumToken *tokens = calloc(sizeof(NumToken), tokens_size);
size_t ridx = tokens_size - 1;
if(ridx >= tokens_size) {
puts("ERROR: Should not be in invalid state");
free(tokens);
return NULL;
}
size_t size;
if(t >= 100) {
switch(t / 100) {
case 1:
size = strlen(ONE HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
unsigned long long temp;
unsigned long long temp_suffix = 0;
char is_first = 1;
while(n > 0) {
temp = n % 1000;
if(temp % 10 > 0) {
tokens[ridx].suffix = temp_suffix;
tokens[ridx].value = temp % 10;
if(is_first) {
tokens[ridx].flags |= 1;
is_first = 0;
}
memcpy((*buf) + *buf_idx, ONE HUNDRED, size);
*buf_idx += size;
break;
case 2:
size = strlen(TWO HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
if(ridx > 0) {
--ridx;
} else {
tokens = doubleTokensBuf(tokens, &tokens_size);
ridx = tokens_size / 2 - 1;
*tokens_size_out = tokens_size;
}
memcpy((*buf) + *buf_idx, TWO HUNDRED, size);
*buf_idx += size;
break;
case 3:
size = strlen(THREE HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
if((temp / 10) % 10 > 0) {
if(ridx + 1 < tokens_size
&& (temp / 10) % 10 == 1
&& tokens[ridx + 1].value > 0
&& tokens[ridx + 1].value <= 9) {
tokens[ridx + 1].value += 10;
} else {
tokens[ridx].suffix = temp_suffix;
tokens[ridx].value = ((temp / 10) % 10) * 10;
if(is_first) {
tokens[ridx].flags |= 1;
is_first = 0;
}
if(ridx > 0) {
--ridx;
} else {
tokens = doubleTokensBuf(tokens, &tokens_size);
ridx = tokens_size / 2 - 1;
*tokens_size_out = tokens_size;
}
}
memcpy((*buf) + *buf_idx, THREE HUNDRED, size);
*buf_idx += size;
break;
case 4:
size = strlen(FOUR HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
if((temp / 100) % 10 > 0) {
tokens[ridx].suffix = temp_suffix;
tokens[ridx].value = ((temp / 100) % 10) * 100;
if(is_first) {
tokens[ridx].flags |= 1;
is_first = 0;
}
memcpy((*buf) + *buf_idx, FOUR HUNDRED, size);
*buf_idx += size;
break;
case 5:
size = strlen(FIVE HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
if(ridx > 0) {
--ridx;
} else {
tokens = doubleTokensBuf(tokens, &tokens_size);
ridx = tokens_size / 2 - 1;
*tokens_size_out = tokens_size;
}
memcpy((*buf) + *buf_idx, FIVE HUNDRED, size);
*buf_idx += size;
break;
case 6:
size = strlen(SIX HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
if(temp_suffix == 0) {
temp_suffix = 1000;
} else {
temp_suffix *= 1000;
}
n /= 1000;
}
return tokens;
}
void appendStringToBuf(char **buf, size_t *buf_idx, size_t *buf_size, const char *str) {
size_t str_size = strlen(str);
while(*buf_idx + str_size + 1 >= *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, str, str_size);
*buf_idx += str_size;
}
const char * tokensToString(NumToken *tokens, size_t tokens_size) {
char *buf = calloc(1, INIT_SEQ_BUF_SIZE);
size_t buf_size = INIT_SEQ_BUF_SIZE;
size_t buf_idx = 0;
for(size_t i = 0; i < tokens_size; ++i) {
if(tokens[i].value == 0 && tokens[i].suffix == 0) {
continue;
}
if(i > 0 && tokens[i].suffix != tokens[i - 1].suffix) {
if(tokens[i - 1].suffix != 0) {
switch(tokens[i - 1].suffix) {
case 1000000000000:
appendStringToBuf(&buf, &buf_idx, &buf_size, TRILLION);
break;
case 1000000000:
appendStringToBuf(&buf, &buf_idx, &buf_size, BILLION);
break;
case 1000000:
appendStringToBuf(&buf, &buf_idx, &buf_size, MILLION);
break;
case 1000:
appendStringToBuf(&buf, &buf_idx, &buf_size, THOUSAND);
break;
default:
puts("ERROR: Unreachable");
free(buf);
return NULL;
}
}
memcpy((*buf) + *buf_idx, SIX HUNDRED, size);
*buf_idx += size;
break;
case 7:
size = strlen(SEVEN HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
if(i + 1 == tokens_size && (tokens[i].flags & 1)) {
switch(tokens[i].value) {
case 1:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIRST);
break;
case 2:
appendStringToBuf(&buf, &buf_idx, &buf_size, SECOND);
break;
case 3:
appendStringToBuf(&buf, &buf_idx, &buf_size, THIRD);
break;
case 4:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOURTH);
break;
case 5:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIFTH);
break;
case 6:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIXTH);
break;
case 7:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVENTH);
break;
case 8:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHTH);
break;
case 9:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINTH);
break;
case 10:
appendStringToBuf(&buf, &buf_idx, &buf_size, TENTH);
break;
case 11:
appendStringToBuf(&buf, &buf_idx, &buf_size, ELEVENTH);
break;
case 12:
appendStringToBuf(&buf, &buf_idx, &buf_size, TWELFTH);
break;
case 13:
appendStringToBuf(&buf, &buf_idx, &buf_size, THIRTEENTH);
break;
case 14:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOURTEENTH);
break;
case 15:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIFTEENTH);
break;
case 16:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIXTEENTH);
break;
case 17:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVENTEENTH);
break;
case 18:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHTEENTH);
break;
case 19:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINETEENTH);
break;
case 20:
appendStringToBuf(&buf, &buf_idx, &buf_size, TWENTIETH);
break;
case 30:
appendStringToBuf(&buf, &buf_idx, &buf_size, THIRTIETH);
break;
case 40:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOURTIETH);
break;
case 50:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIFTIETH);
break;
case 60:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIXTIETH);
break;
case 70:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVENTIETH);
break;
case 80:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHTIETH);
break;
case 90:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINETIETH);
break;
case 100:
appendStringToBuf(&buf, &buf_idx, &buf_size, ONE HUNDREDTH);
break;
case 200:
appendStringToBuf(&buf, &buf_idx, &buf_size, TWO HUNDREDTH);
break;
case 300:
appendStringToBuf(&buf, &buf_idx, &buf_size, THREE HUNDREDTH);
break;
case 400:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOUR HUNDREDTH);
break;
case 500:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIVE HUNDREDTH);
break;
case 600:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIX HUNDREDTH);
break;
case 700:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVEN HUNDREDTH);
break;
case 800:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHT HUNDREDTH);
break;
case 900:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINE HUNDREDTH);
break;
default:
puts("ERROR: Unreachable");
free(buf);
return NULL;
}
memcpy((*buf) + *buf_idx, SEVEN HUNDRED, size);
*buf_idx += size;
break;
case 8:
size = strlen(EIGHT HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
} else {
switch(tokens[i].value) {
case 1:
appendStringToBuf(&buf, &buf_idx, &buf_size, ONE);
break;
case 2:
appendStringToBuf(&buf, &buf_idx, &buf_size, TWO);
break;
case 3:
appendStringToBuf(&buf, &buf_idx, &buf_size, THREE);
break;
case 4:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOUR);
break;
case 5:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIVE);
break;
case 6:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIX);
break;
case 7:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVEN);
break;
case 8:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHT);
break;
case 9:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINE);
break;
case 10:
appendStringToBuf(&buf, &buf_idx, &buf_size, TEN);
break;
case 11:
appendStringToBuf(&buf, &buf_idx, &buf_size, ELEVEN);
break;
case 12:
appendStringToBuf(&buf, &buf_idx, &buf_size, TWELVE);
break;
case 13:
appendStringToBuf(&buf, &buf_idx, &buf_size, THIRTEEN);
break;
case 14:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOURTEEN);
break;
case 15:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIFTEEN);
break;
case 16:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIXTEEN);
break;
case 17:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVENTEEN);
break;
case 18:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHTEEN);
break;
case 19:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINETEEN);
break;
case 20:
appendStringToBuf(&buf, &buf_idx, &buf_size, TWENTY);
break;
case 30:
appendStringToBuf(&buf, &buf_idx, &buf_size, THIRTY);
break;
case 40:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOURTY);
break;
case 50:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIFTY);
break;
case 60:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIXTY);
break;
case 70:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVENTY);
break;
case 80:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHTY);
break;
case 90:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINETY);
break;
case 100:
appendStringToBuf(&buf, &buf_idx, &buf_size, ONE HUNDRED);
break;
case 200:
appendStringToBuf(&buf, &buf_idx, &buf_size, TWO HUNDRED);
break;
case 300:
appendStringToBuf(&buf, &buf_idx, &buf_size, THREE HUNDRED);
break;
case 400:
appendStringToBuf(&buf, &buf_idx, &buf_size, FOUR HUNDRED);
break;
case 500:
appendStringToBuf(&buf, &buf_idx, &buf_size, FIVE HUNDRED);
break;
case 600:
appendStringToBuf(&buf, &buf_idx, &buf_size, SIX HUNDRED);
break;
case 700:
appendStringToBuf(&buf, &buf_idx, &buf_size, SEVEN HUNDRED);
break;
case 800:
appendStringToBuf(&buf, &buf_idx, &buf_size, EIGHT HUNDRED);
break;
case 900:
appendStringToBuf(&buf, &buf_idx, &buf_size, NINE HUNDRED);
break;
default:
puts("ERROR: Unreachable");
free(buf);
return NULL;
}
memcpy((*buf) + *buf_idx, EIGHT HUNDRED, size);
*buf_idx += size;
break;
case 9:
size = strlen(NINE HUNDRED);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, NINE HUNDRED, size);
*buf_idx += size;
break;
default:
break;
}
}
if((t % 100) >= 10) {
switch((t % 100) / 10) {
case 1:
if(t % 10 > 0) {
if((t % 10) > 0) {
switch(t % 10) {
case 1:
size = strlen(ELEVENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, ELEVENTH, size);
*buf_idx += size;
break;
case 2:
size = strlen(TWELFTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, TWELFTH, size);
*buf_idx += size;
break;
case 3:
size = strlen(THIRTEENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, THIRTEENTH, size);
*buf_idx += size;
break;
case 4:
size = strlen(FOURTEENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, FOURTEENTH, size);
*buf_idx += size;
break;
case 5:
size = strlen(FIFTEENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, FIFTEENTH, size);
*buf_idx += size;
break;
case 6:
size = strlen(SIXTEENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, SIXTEENTH, size);
*buf_idx += size;
break;
case 7:
size = strlen(SEVENTEENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, SEVENTEENTH, size);
*buf_idx += size;
break;
case 8:
size = strlen(EIGHTEENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, EIGHTEENTH, size);
*buf_idx += size;
break;
case 9:
size = strlen(NINETEENTH);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, NINETEENTH, size);
*buf_idx += size;
break;
default:
puts("ERROR: Unreachable");
break;
}
}
return;
} else {
size = strlen(TEN);
if(size >= *buf_idx + *buf_size) {
doubleBufSize(buf, buf_size);
}
memcpy((*buf) + *buf_idx, TEN, size);
*buf_idx += size;
}
if(tokens[tokens_size - 1].suffix > 0) {
switch(tokens[tokens_size - 1].suffix) {
case 1000000000000:
appendStringToBuf(&buf, &buf_idx, &buf_size, TRILLIONTH);
break;
case 2:
case 1000000000:
appendStringToBuf(&buf, &buf_idx, &buf_size, BILLIONTH);
break;
case 3:
case 1000000:
appendStringToBuf(&buf, &buf_idx, &buf_size, MILLIONTH);
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
case 1000:
appendStringToBuf(&buf, &buf_idx, &buf_size, THOUSANDTH);
break;
default:
puts("ERROR: Unreachable");
break;
}
}
if((t % 10) > 0) {
switch(t % 10) {
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
default:
break;
free(buf);
return NULL;
}
}
return buf;
}
const char * numberToString(unsigned long long n) {
char *buf = calloc(1, INIT_SEQ_NUM_TO_STR_SIZE);
size_t buf_idx = 0;
size_t buf_size = INIT_SEQ_NUM_TO_STR_SIZE;
if(n / 1000000000000 > 0) {
}
if((n % 1000000000000) / 1000000000 > 0) {
}
if((n % 1000000000) / 1000000 > 0) {
}
if((n % 1000000) / 1000 > 0) {
}
if((n % 1000) / 100 > 0) {
}
if((n % 100) / 10 > 0) {
}
if(n % 10) {
}
size_t tokens_size;
NumToken *tokens = numberToTokens(n, &tokens_size);
const char *str = tokensToString(tokens, tokens_size);
free(tokens);
return str;
}

View file

@ -4,7 +4,9 @@
#include <string.h>
#include <stdlib.h>
#define INIT_SEQ_BUF_SIZE 1024
#define INIT_SEQ_NUM_TO_STR_SIZE 128
#define INIT_SEQ_NUM_TOKENS_SIZE 8
#define FIRST "first"
#define SECOND "second"
@ -14,7 +16,7 @@
#define SIXTH "sixth"
#define SEVENTH "seventh"
#define EIGHTH "eighth"
#define NINTH "ningth"
#define NINTH "ninth"
#define TENTH "tenth"
#define ELEVENTH "eleventh"
@ -39,6 +41,16 @@
#define NINE "nine"
#define TEN "ten"
#define ELEVEN "eleven"
#define TWELVE "twelve"
#define THIRTEEN "thirteen"
#define FOURTEEN "fourteen"
#define FIFTEEN "fifteen"
#define SIXTEEN "sixteen"
#define SEVENTEEN "seventeen"
#define EIGHTEEN "eighteen"
#define NINETEEN "nineteen"
#define TWENTY "twenty"
#define THIRTY "thirty"
#define FOURTY "fourty"
@ -49,7 +61,7 @@
#define NINETY "ninety"
#define TWENTIETH "twentieth"
#define THRITIETH "thirtieth"
#define THIRTIETH "thirtieth"
#define FOURTIETH "fourtieth"
#define FIFTIETH "fiftieth"
#define SIXTIETH "sixtieth"
@ -69,14 +81,30 @@
#define BILLIONTH "billionth"
#define TRILLIONTH "trillionth"
void doubleBufSize(char **buf, size_t *buf_size);
void thousandToString(char **buf, size_t *buf_idx, size_t *buf_size, unsigned long long t, int last);
typedef struct NumToken {
unsigned long long value;
unsigned long long suffix;
char flags; // 0b0001 - last value
} NumToken;
/*!
* \brief Returns a word-based number string from the input number.
* \brief Convert a number to tokens
*
* \warning The returned pointer must be free'd eventually.
* \warning The returned pointer must be eventually free'd
*/
NumToken * numberToTokens(unsigned long long n, size_t *tokens_size);
/*!
* \brief Convert tokens to a string
*
* \warning The returned pointer must be eventually free'd
*/
const char * tokensToString(NumToken *tokens, size_t tokens_size);
/*!
* \brief Convert a number to a string
*
* \warning The returned pointer must be eventually free'd
*/
const char * numberToString(unsigned long long n);