Skip to content

Instantly share code, notes, and snippets.

@svagionitis
Last active September 27, 2020 12:01
Show Gist options
  • Save svagionitis/2f9c9ddc4dc760845beb to your computer and use it in GitHub Desktop.
Save svagionitis/2f9c9ddc4dc760845beb to your computer and use it in GitHub Desktop.
Implement the look and say sequence in C. More info about the look and say sequence here http://en.wikipedia.org/wiki/Look-and-say_sequence
/**
* @file look_and_say_seq.c
* @author Stavros Vagionitis
* @date 01 Feb 2015
* @brief Implement the look and say sequence. More info
* here http://en.wikipedia.org/wiki/Look-and-say_sequence
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
/**
* \brief Swap pointers
*
* \param p1 [IN/OUT] First pointer
* \param p2 [IN/OUT] Second pointer
*/
void swap_ptr(uint8_t **p1, uint8_t **p2)
{
if (!p1 && !*p1)
return;
if (!p2 && !*p2)
return;
uint8_t *tmp = *p2;
*p2 = *p1;
*p1 = tmp;
}
/**
* \brief Update the sequence giving the previous sequence.
*
* \param seq [IN] The previous sequence
* \param sizeof_seq [IN] The size of the previous sequence.
* \param new_seq [OUT] The new sequence
* \param sizeof_new_seq [OUT] The size of the new sequence.
* \return 1 if everything is ok, 0 if not.
*/
uint8_t update_seq(const uint8_t *seq, const uint64_t sizeof_seq, uint8_t **new_seq, uint64_t *sizeof_new_seq)
{
if(*new_seq)
*new_seq = NULL;
*sizeof_new_seq = 0;
if (seq == NULL)
{
fprintf(stderr, "%s:%d seq is NULL\n", __func__, __LINE__);
return 0;
}
uint8_t *tmp = NULL;
uint64_t counter = 0;
for (uint64_t i = 0;i<sizeof_seq;i++)
{
tmp = NULL;
if (i == 0)
counter++;
if (i > 0)
{
// If the current digit is the same
// with the previous add it to the
// counter.
if (seq[i-1] == seq[i])
counter++;
else
{
// If the current digit is not the same
// with the previous, then allocate two
// places in the new sequence, one for the
// counter and the other for the previous digit.
*sizeof_new_seq += 2;
tmp = realloc(*new_seq, *sizeof_new_seq * sizeof(uint8_t));
if (tmp != NULL)
*new_seq = tmp;
else
{
fprintf(stderr, "%s:%d Mem Alloc failed\n", __func__, __LINE__);
if (*new_seq)
free(*new_seq);
return 0;
}
(*new_seq)[*sizeof_new_seq - 2] = counter;
(*new_seq)[*sizeof_new_seq - 1] = seq[i-1];
// Start counter from 1 for
// counting the current digit.
counter = 1;
}
}
// The last number in sequence.
if (i == sizeof_seq - 1)
{
*sizeof_new_seq += 2;
tmp = realloc(*new_seq, *sizeof_new_seq * sizeof(uint8_t));
if (tmp != NULL)
*new_seq = tmp;
else
{
fprintf(stderr, "%s:%d Mem Alloc failed\n", __func__, __LINE__);
if (*new_seq)
free(*new_seq);
return 0;
}
(*new_seq)[*sizeof_new_seq - 2] = counter;
(*new_seq)[*sizeof_new_seq - 1] = seq[i];
}
}
return 1;
}
/**
* \brief Print the sequence numbers in a line.
*
* \param seq [IN] The sequence itself.
* \param size_seq [IN] The size of the sequence.
* \return 1 if everything is ok, 0 if not.
*/
uint8_t print_seq(const uint8_t *seq, const uint64_t size_seq)
{
if (seq == NULL)
{
fprintf(stderr, "%s:%d seq is NULL\n", __func__, __LINE__);
return 0;
}
for (uint64_t i = 0;i<size_seq;i++)
{
if (i != size_seq-1)
fprintf(stdout, "%u", seq[i]);
else
fprintf(stdout, "%u -- %llu\n", seq[i], size_seq);
}
return 1;
}
/**
* \brief Count digits of an unsigned integer
*
* \param num [IN] The number to count the digits
* \return the number of digits.
*/
uint64_t count_digits(const uint64_t num)
{
uint64_t c = 0;
uint64_t n = num;
while(n)
{
n/=10;
c++;
}
return c;
}
void usage(char *argv0)
{
fprintf(stdout, "%s [starting value] [iterations]\n", argv0);
exit(0);
}
int main(int argc, char *argv[])
{
uint64_t start = 0;
uint64_t total_iter = 0;
if (argc != 3)
usage(argv[0]);
if (argv[1])
start = (uint64_t)atoi(argv[1]);
else
usage(argv[0]);
if (argv[2])
total_iter = (uint64_t)atoi(argv[2]);
else
usage(argv[0]);
// Current sequence.
uint8_t *seq = NULL;
uint64_t seq_size = count_digits(start);
seq = malloc(seq_size * sizeof(uint8_t));
// Convert the starting number in a number sequence
int d = 0;
for(d = seq_size - 1; d >= 0;d--)
{
seq[d] = start % 10;
start /= 10;
}
// New sequence.
uint8_t *new_seq = NULL;
uint64_t new_seq_size = 0;
for (uint64_t i = 0;i<total_iter;i++)
{
update_seq(seq, seq_size, &new_seq, &new_seq_size);
print_seq(new_seq, new_seq_size);
seq_size = new_seq_size;
new_seq_size = 0;
swap_ptr(&seq, &new_seq);
if (new_seq)
free(new_seq);
}
if (seq)
free(seq);
return 0;
}
all: look_and_say_seq
look_and_say_seq: look_and_say_seq.c
gcc -o look_and_say_seq -O2 -Wall -W -ansi -pedantic -std=gnu99 look_and_say_seq.c
clean:
rm -rf look_and_say_seq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment