Task: Summarize and say sequence

C: #include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct rec_t rec_t;
struct rec_t {
	int depth;
	rec_t * p[10];
};

rec_t root = {0, {0}};

#define USE_POOL_ALLOC
#ifdef USE_POOL_ALLOC 
rec_t *tail = 0, *head = 0;
#define POOL_SIZE (1 << 20)
inline rec_t *new_rec()
{
	if (head == tail) {
		head = calloc(sizeof(rec_t), POOL_SIZE);
		tail = head + POOL_SIZE;
	}
	return head++;
}
#else
#define new_rec() calloc(sizeof(rec_t), 1)
#endif

rec_t *find_rec(char *s)
{
	int i;
	rec_t *r = &root;
	while (*s) {
		i = *s++ - '0';
		if (!r->p[i]) r->p[i] = new_rec();
		r = r->p[i];
	}
	return r;
}


char number[100][4];
void init()
{
	int i;
	for (i = 0; i < 100; i++)
		sprintf(number[i], "%d", i);
}

void count(char *buf)
{
	int i, c[10] = {0};
	char *s;

	for (s = buf; *s; c[*s++ - '0']++);

	for (i = 9; i >= 0; i--) {
		if (!c[i]) continue;
		s = number[c[i]];

		*buf++ = s[0];
		if ((*buf = s[1])) buf++;

		*buf++ = i + '0';
	}

	*buf = '\0';
}

int depth(char *in, int d)
{
	rec_t *r = find_rec(in);

	if (r->depth > 0)
		return r->depth;

	d++;
	if (!r->depth)	r->depth = -d;
	else		r->depth += d;

	count(in);
	d = depth(in, d);

	if (r->depth <= 0) r->depth = d + 1;
	return r->depth;
}

int main(void)
{
	char a[100];
	int i, d, best_len = 0, n_best = 0;
	int best_ints[32];
	rec_t *r;

	init();

	for (i = 0; i < 1000000; i++) {
		sprintf(a, "%d", i);
		d = depth(a, 0);

		if (d < best_len) continue;
		if (d > best_len) {
			n_best = 0;
			best_len = d;
		}
		if (d == best_len)
			best_ints[n_best++] = i;
	}

	printf("longest length: %d\n", best_len);
	for (i = 0; i < n_best; i++) {
		printf("%d\n", best_ints[i]);
		sprintf(a, "%d", best_ints[i]);
		for (d = 0; d <= best_len; d++) {
			r = find_rec(a);
			printf("%3d: %s\n", r->depth, a);
			count(a);
		}
		putchar('\n');
	}

	return 0;
}











Ada: with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
procedure SelfRef is
   subtype Seed is Natural range 0 .. 1_000_000;
   subtype Num is Natural range 0 .. 10;
   type NumList is array (0 .. 10) of Num;
   package IO is new Ada.Text_IO.Integer_IO (Natural);
   package DVect is new Ada.Containers.Vectors (Positive, NumList);

   function Init (innum : Seed) return NumList is
      list : NumList := (others => 0);
      number : Seed := innum;  d : Num;
   begin
      loop
         d := Num (number mod 10);
         list (d) :=  list (d) + 1;
         number := number / 10; exit when number = 0;
      end loop; return list;
   end Init;

   procedure Next (inoutlist : in out NumList) is
      list : NumList := (others => 0);
   begin
      for i in list'Range loop
         if inoutlist (i) /= 0 then
            list (i) := list (i) + 1;
            list (inoutlist (i)) := list (inoutlist (i)) + 1;
         end if;
      end loop; inoutlist := list;
   end Next;

   procedure Show (list : NumList) is begin
      for i in reverse list'Range loop
         if list (i) > 0 then
            IO.Put (list (i), Width => 1); IO.Put (i, Width => 1);
         end if;
      end loop; New_Line;
   end Show;

   function Iterate (theseed : Seed; p : Boolean) return Natural is
      list : NumList := Init (theseed);
      vect : DVect.Vector;
   begin
      vect.Append (list);
      loop
         if p then Show (list); end if;
         Next (list); exit when vect.Contains (list); vect.Append (list);
      end loop;
      return Integer (DVect.Length (vect)) + 1;
   end Iterate;

   mseed : Seed;
   len, maxlen : Natural := 0;
begin
   for i in Seed'Range loop
      len := Iterate (i, False);
      if len > maxlen then mseed := i; maxlen := len; end if;
   end loop;
   IO.Put (maxlen, Width => 1); Put_Line (" Iterations:");
   IO.Put (mseed, Width => 1); New_Line;
   len := Iterate (mseed, True);
end SelfRef;