Подтвердить что ты не робот

Сортировка чисел от 1 до 999 999 999 слов в виде строк

Интересная головоломка программирования:

Если целые числа от 1 до 999 999 999 написаны как слова, отсортированные в алфавитном порядке и конкатенированных, что это 51-миллиардная буква?

Если быть точным: если целые числа от 1 до 999 999 999 выражены словами (опуская пробелы, и, и пунктуация - см. примечание ниже для формата) и отсортировано в алфавитном порядке, чтобы первые шесть целые числа

  • восемь
  • восемнадцать
  • eighteenmillion
  • eighteenmillioneight
  • eighteenmillioneighteen
  • eighteenmillioneighteenthousand

а последнее -

  • twothousandtwohundredtwo

затем чтение сверху вниз, слева справа, 28-я буква завершает написание целого числа "Eighteenmillion".

И еще 51 миллиардная буква написание целого числа. Который из, и какова сумма всех целые числа в эту точку?

Примечание. Например, 911,610,034 написано "Ninehundredelevenmillionsixhundredtenthousandthirtyfour"; Написано 500 000 000 "Fivehundredmillion"; 1,709 написано "Onethousandsevenhundrednine".

Я наткнулся на это в блоге программирования 'Occuallyally Sane' и не мог придумать аккуратный способ сделать это, автор из соответствующий пост говорит, что его первоначальная попытка через 1,5 ГБ памяти заработала через 10 минут, и он сделал это только до 20 000 000 ( "twentymillion" ).

Может ли любой думать о придумать поделиться с группой новым/умным подходом к этому?

4b9b3361

Ответ 1

Изменить: разрешено!

Вы можете создать генератор, который выводит числа в отсортированном порядке. Существует несколько правил сравнения конкатенированных строк, которые, как мне кажется, большинство из нас знают неявно:

  • a < a + b, где b не равно null.
  • a + b < a + c, где b < с.
  • a + b < c + d, где a < c, a не является подмножеством c.

Если вы начинаете с отсортированного списка первых 1000 номеров, вы можете легко сгенерировать остальные, добавив "тысячу" или "миллион" и объединив еще одну группу из 1000.

Здесь полный код в Python:

import heapq

first_thousand=[('', 0), ('one', 1), ('two', 2), ('three', 3), ('four', 4),
                ('five', 5), ('six', 6), ('seven', 7), ('eight', 8),
                ('nine', 9), ('ten', 10), ('eleven', 11), ('twelve', 12),
                ('thirteen', 13), ('fourteen', 14), ('fifteen', 15),
                ('sixteen', 16), ('seventeen', 17), ('eighteen', 18),
                ('nineteen', 19)]
tens_name = (None, 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty',
             'seventy','eighty','ninety')
for number in range(20, 100):
    name = tens_name[number/10] + first_thousand[number%10][0]
    first_thousand.append((name, number))
for number in range(100, 1000):
    name = first_thousand[number/100][0] + 'hundred' + first_thousand[number%100][0]
    first_thousand.append((name, number))

first_thousand.sort()

def make_sequence(base_generator, suffix, multiplier):
    prefix_list = [(name+suffix, number*multiplier)
                   for name, number in first_thousand[1:]]
    prefix_list.sort()
    for prefix_name, base_number in prefix_list:
        for name, number in base_generator():
            yield prefix_name + name, base_number + number
    return

def thousand_sequence():
    for name, number in first_thousand:
        yield name, number
    return

def million_sequence():
    return heapq.merge(first_thousand,
                       make_sequence(thousand_sequence, 'thousand', 1000))

def billion_sequence():
    return heapq.merge(million_sequence(),
                       make_sequence(million_sequence, 'million', 1000000))

def solve(stopping_size = 51000000000):
    total_chars = 0
    total_sum = 0
    for name, number in billion_sequence():
        total_chars += len(name)
        total_sum += number
        if total_chars >= stopping_size:
            break
    return total_chars, total_sum, name, number

Прошло немного времени, около часа. 51-й миллионный персонаж является последним персонажем шестисотдесятидесяти миллисекундсостоящих столетий, а сумма целых чисел до этой точки - 413,540,008,163,475,743.

Ответ 2

Я бы отсортировал имена первых 20 целых чисел и имена десятков, сотен и тысяч, выяснил, сколько чисел начинается с каждого из них, и оттуда.

Например, первые несколько [ eight, eighteen, eighthundred, eightmillion, eightthousand, eighty, eleven, ....

Числа, начинающиеся с "восьмерки", равны 8. С "восьмеркой", 800-899, 800 000-899999, 800 000 000-899 999 999. И так далее.

Число букв в конкатенации слов для 0 (представленное пустой строкой) до 99 может быть найдено и суммировано; это можно умножить на "тыс." = 8 или "млн." = 7 для более высоких диапазонов. Значение 800-899 будет в 100 раз больше длины "восьмерки" плюс длина 0-99. И так далее.

Ответ 3

У этого парня есть решение головоломки, написанной в Haskell. По-видимому, Майкл Боргвардт был прав в использовании Trie для поиска решения.

Ответ 4

Эти строки будут иметь множество и множество общих префиксов - идеальный вариант использования trie, который резко сократит память использование и, возможно, также время работы.

Ответ 5

(Первая попытка в этом неверна, но я оставлю ее, потому что более полезно видеть ошибки на пути к решению чего-то, а не только окончательного ответа.)

Сначала я бы сгенерировал строки от 0 до 999 и сохранил их в массиве, называемом тысячами. Элемент 0 является ", а" " представляет пробел в списках ниже.

Настройка тысячString использует следующее:

Units: "" one two three ... nine

Teens: ten eleven twelve ... nineteen

Tens: "" "" twenty thirty forty ... ninety

Настройка тысячString выглядит примерно так:

thousandsString[0] = ""

for (i in 1..10)
   thousandsString[i] = Units[i]
end

for (i in 10..19)
   thousandsString[i] = Teens[i]
end

for (i in 20..99)
   thousandsString[i] = Tens[i/10] + Units[i%10]
end

for (i in 100..999)
   thousandsString[i] = Units[i/100] + "hundred" + thousandsString[i%100]
end

Затем я отсортировал бы этот массив в алфавитном порядке.

Тогда, если t1 t2 t3 - это строки, взятые из тысячString, все строки имеют вид

t1

ИЛИ

t1 + million + t2 + тыс. + t3

ИЛИ

t1 + тыс. + t2

Чтобы выводить их в правильном порядке, я обрабатывал отдельные строки, за которыми следуют миллионы строк, за которыми следуют строки + тысячи.

foreach (t1 in thousandsStrings)

   if (t1 == "")
     continue;

   process(t1)

   foreach (t2 in thousandsStrings)
      foreach (t3 in thousandsStrings)
         process (t1 + "million" + t2 + "thousand" + t3)
      end
   end

   foreach (t2 in thousandsStrings)
       process (t1 + "thousand" + t2)
   end
end

где процесс означает сохранение предыдущей суммы, а затем добавляет новую длину строки к сумме, и если новая сумма равнa >= ваша целевая сумма, вы выплевываете результаты и, возможно, возвращаетесь или выходите из циклов, независимо от того, делает тебя счастливым.

=============================================== ======================

Вторая попытка, другие ответы были правильными, что вам нужно использовать 3k строки вместо строк 1k в качестве базы.

Начните с тысячиString сверху, но оставьте пустой "" для нуля. Это оставляет 999 элементов и вызывает это uStr (строка единиц).

Создайте еще два набора:

tStr = the set of all uStr + "thousand"

mStr = the set of all uStr + "million"

Теперь создайте еще два объединения:

mtuStr = mStr union tStr union uStr

tuStr = tStr union uStr

Закажите uStr, tuStr, mtuStr

Теперь цикл и логика здесь немного отличаются от предыдущих.

foreach (s1 in mtuStr)
   process(s1)

   // If this is a millions or thousands string, add the extra strings that can
   // go after the millions or thousands parts.

   if (s1.contains("million"))
      foreach (s2 in tuStr)
         process (s1+s2)          

         if (s2.contains("thousand"))
            foreach (s3 in uStr)
               process (s1+s2+s3)
            end
         end
      end
   end

   if (s1.contains("thousand"))
      foreach (s2 in uStr)
         process (s1+s2)
      end
   end
end

Ответ 6

Здесь мое решение python, которое выдает правильный ответ за долю секунды. Я вообще не программист на питоне, поэтому приношу извинения за любые вопиющие ошибки стиля кода.

#!/usr/bin/env python

import sys

ONES=[
    "",         "one",      "two",      "three",        "four", 
    "five",     "six",      "seven",    "eight",        "nine",
    "ten",      "eleven",   "twelve",   "thirteen",     "fourteen",
    "fifteen",  "sixteen",  "seventeen","eighteen",     "nineteen",
]
TENS=[
    "zero",     "ten",      "twenty",   "thirty",       "forty",
    "fifty",    "sixty",    "seventy",  "eighty",       "ninety",
]

def to_s_h(i):
    if(i<20):
        return(ONES[i])
    return(TENS[i/10] + ONES[i%10]) 

def to_s_t(i):
    if(i<100):
        return(to_s_h(i))
    return(ONES[i/100] + "hundred" + to_s_h(i%100))

def to_s_m(i):
    if(i<1000):
        return(to_s_t(i))
    return(to_s_t(i/1000) + "thousand" + to_s_t(i%1000))

def to_s_b(i):
    if(i<1000000):
        return(to_s_m(i))
    return(to_s_m(i/1000000) + "million" + to_s_m(i%1000000))


def try_string(s,t):
    global letters_to_go,word_sum
    l=len(s)
    letters_to_go -= l
    word_sum += t
    if(letters_to_go == 0):
        print "solved: " + s
        print "sum is: " + str(word_sum)
        sys.exit(0)
    elif(letters_to_go < 0):
        print "failed: " + s + " " + str(letters_to_go)
        sys.exit(-1)

def solve(depth,prefix,prefix_num):
    global millions,thousands,ones,letters_to_go,onelen,thousandlen,word_sum
    src=[ millions,thousands,ones ][depth]
    for x in src:
        num=prefix + x[2]
        nn=prefix_num+x[1]
        try_string(num,nn)
        if(x[0] == 0):
            continue
        if(x[0] == 1):
            stl=(len(num) * 999) + onelen
            ss=(nn*999) + onesum
        else:
            stl=(len(num) * 999999) + thousandlen + onelen*999
            ss=(nn*999999) + thousandsum
        if(stl < letters_to_go):
            letters_to_go -= stl
            word_sum += ss
        else:
            solve(depth+1,num,nn)


ones=[]
thousands=[]
millions=[]
onelen=0
thousandlen=0
onesum=(999*1000)/2
thousandsum=(999999*1000000)/2



for x in range(1,1000):
    s=to_s_b(x)
    l=len(s)
    ones.append( (0,x,s) )
    onelen += l
    thousands.append( (0,x,s) )
    thousands.append( (1,x*1000,s + "thousand") )
    thousandlen += l + (l+len("thousand"))*1000
    millions.append( (0,x,s) )
    millions.append( (1,x*1000,s + "thousand") )
    millions.append( (2,x*1000000,s + "million") )

ones.sort(key=lambda x: x[2])
thousands.sort(key=lambda x: x[2])
millions.sort(key=lambda x: x[2])

letters_to_go=51000000000
word_sum=0

solve(0,"",0)

Он работает, предварительно вычисляя длину чисел от 1.999 и 1.999999, чтобы он мог пропускать целые поддеревья, если не знает, что ответ лежит где-то внутри них.

Ответ 7

Что я сделал: 1) Итерация через 1 - 999 и генерация слов для каждого из них. По мере создания: 2) Создайте 3 структуры данных, где каждый node имеет указатель на дочерние элементы, а каждый node имеет значение символа и указатель на Siblings. (Двоичное дерево, на самом деле, но мы не хотим думать об этом таким образом обязательно - для меня это легче концептуализировать как список братьев и сестер со списками детей, зависающих, но если вы думаете об этом (нарисуйте рис. } вы поймете, что это на самом деле двоичное дерево). Эти 3 структуры данных создаются следующим образом: а) первый со словом, сгенерированным (т.е. 1-999, отсортированным по алфавиту) б) все значения в первом + все значения с добавлением "тыс." (т.е. 1-999 и 1000-999 000 (шаг 1000) (всего значений в 1998 г.) c) все значения в B + все значения в с миллионом прилагаемых (всего 2997 значений) 3) Для каждого листа node в (b) добавьте Child as (a). Для каждого листа node в (c) добавьте ребенка как (b). 4) Пройдите по дереву, подсчитав, сколько персонажей мы проходим и останавливаемся на 51 миллиард.

ПРИМЕЧАНИЕ. Это не суммирует значения (я не читал этот бит, когда я изначально это сделал), и работает чуть более 3 минут (около 192 секунд обычно, используя С++). ПРИМЕЧАНИЕ 2: (в случае, если это не очевидно) хранится только 5 994 значения, но они хранятся таким образом, что через дерево

Я сделал это примерно год-два назад, когда я наткнулся на него, и с тех пор понял, что существует множество оптимизаций (самый длинный бит - это движение по дереву - ДОЛГОЙ ПУТЬ). Есть несколько оптимизаций, которые, по моему мнению, значительно улучшат этот подход, но я никогда не буду беспокоиться об этом, кроме как оптимизировать избыточные узлы в дереве, чтобы они сохраняли строки, а не символы

Я видел, как люди утверждают, что они решили его менее чем за 5 секунд....

Ответ 8

странная, но забавная идея.

постройте разреженный список длин числа от 0 до 9, затем 10-90 на десятки, затем 100, 1000 и т.д., до миллиарда, индексы - это значение целой части, длина которой сохраняется.

напишите функцию для вычисления числа в виде длины строки, используя таблицу. (разбивая число на части и просматривая длину aprts, никогда не создавая строку).

тогда вы выполняете математику только по мере прохождения чисел, вычисляя длину из таблица после суммирования для вашей суммы.

с суммой и значением конечного целого числа, определите целое число, которое будет записано, и volia, вы закончили.

Ответ 9

Да, я снова, но совершенно другой подход.

Просто, вместо того, чтобы хранить слова "onethousandeleventyseven", вы пишете сортировку, чтобы использовать ее при сравнении.

Crude java POC:

public class BillionsBillions implements Comparator {
    public int compare(Object a, Object b) {
        String s1 = (String)a; // "1234";
        String s2 = (String)b; // "1235";

        int n1 = Integer.valueOf(s1);
        int n2 = Integer.valueOf(s2);

        String w1 = numberToWords(n1);
        String w2 = numberToWords(n2);

        return w1.compare(w2);
    }

    public static void main(String args[]) {
        long numbers[] = new long[1000000000]; // Bring your 64 bit JVMs

        for(int i = 0; i < 1000000000; i++) {
            numbers[i] = i;
        }

        Arrays.sort(numbers, 0, numbers.length, new BillionsBillions());

        long total = 0;

        for(int i : numbers) {
            String l = numberToWords(i);
            long offset = total + l - 51000000000;

            if (offset >= 0) {
                String c = l.substring(l - offset, l - offset + 1);
                System.out.println(c);
                break;
            }
         }
    }
}

"numberToWords" оставлен как упражнение для читателя.

Ответ 10

Вам нужно сохранить всю строку в памяти?

Если нет, просто сохраните, сколько символов вы уже добавили. Для каждой итерации вы проверяете длину следующего текстового представления. Если он превышает букву, которую вы ищете, буква должна быть в этой строке, поэтому извлеките ее им индексированием, распечатайте и остановите выполнение. В противном случае добавьте длину строки в число символов и перейдите к следующему номеру.

Ответ 11

Все строки начинаются с одной, десяти, двух, двадцать, трех, тридцати, четырех и т.д., поэтому я начну с выяснения, сколько из них в каждом из ковши, Тогда вы должны хотя бы знать, в каком ведре вам нужно подойти ближе.

Затем я бы посмотрел на подразделение ведер дальше на основе возможных префиксов. Например, в течение девятисот, вы будете иметь все те же самые ведра, с которыми вам приходилось начинать, только для чисел, начинающихся с 900.

Ответ 12

Вопрос заключается в эффективном хранении данных, а не в строковых манипуляциях. Создайте enum для представления слов. слова должны отображаться в упорядоченном порядке, так что когда придет время сортировать, это простое сравнение. Теперь создайте список и выполните сортировку. используйте тот факт, что вы знаете, как долго каждое слово связано с перечислением, чтобы добавить персонажа, который вам нужен.

Ответ 13

Честно говоря, я бы позволил RDBMS, как SQL Server или Oracle, сделать для меня работу.

  • Вставьте миллиарды строк в индексированную таблицу.
  • Вычислить столбец длины строки.
  • Начните снимать верхние X-записи за раз с SUM, пока я не доберусь до 51 миллиарда.

Мог бы немного побить сервер, так как ему нужно было бы сделать много дискового ввода-вывода, но в целом я думаю, что я мог бы найти ответ быстрее, чем тот, кто напишет программу для этого.

Иногда просто делать это - это то, что действительно хочет клиент, и может заботиться о том, какой фантастический шаблон дизайна или структура данных вы использовали.

Ответ 14

У вас есть один миллиард чисел и 51 миллиард символов - есть хороший шанс, что это трюк, так как в каждом из них в среднем 51 символ. Суммируйте конверсии всех чисел и посмотрите, добавляет ли она до 51 миллиарда.

Изменить: оно добавляет до 70 305 000 000 символов, поэтому это неправильный ответ.

Ответ 15

Код выигрывает...

#!/bin/bash
n=0
while [ $n -lt 1000000000 ]; do
   number -l $n | sed -e 's/[^a-z]//g'
   let n=n+1
done | sort > /tmp/bignumbers
awk '
BEGIN {
    total = 0;
}
{
    l = length($0); 
    offset = total + l - 51000000000;
    print total " " offset
    if (offset >= 0) {
        c = substr($0, l - offset, 1);
        print c;
        exit;
    }
    total = total + l;
}' /tmp/bignumbers

Протестировано для гораздо меньшего диапазона;-). Требуется много дискового пространства, сжатая файловая система будет, ммм, ценной, но не так много памяти.

У сортировки есть опции для сжатия рабочих файлов, а также вы можете загружать gzip для прямого сжатия данных.

Не самое крутое решение.

Но он работает.

Ответ 16

укажите длины для 1-999 и включите длину для 0 как 0.

Итак, теперь у вас есть массив для 0-999, а именно uint32 sizes999 [1000]; (не собираюсь вдаваться в подробности создания этого) также требуется массив из тысячи последних букв last_letters [1000] (опять же не собираюсь вдаваться в подробности генерации этого, поскольку это еще проще даже сотни d даже десятки y, за исключением 10, которые n других циклов, хотя последний из e через nin e ноль невозможен)

uint32 sizes999[1000];

uint64 totallen = 0;
strlen_million = strlen("million");
strlen_thousand = strlen("thousand");
for (uint32 i = 0; i<1000;++i){
    for (uint32 j = 0; j<1000;++j){
        for (uint32 j = 0; j<1000;++j){ 
           total_len += sizes999[i]+strlen_million + 
                        sizes999[j]+strlen_thousand +
                        sizes999[k];
           if totallen == 51000000000 goto done;
           ASSERT(totallen <51000000000);//he claimed  51000000000 was not intermediate
        }
    }
}
done:

//теперь используйте я j k для получения последней буквы с помощью last_letters999

//думаем о i, j, k как цифре base 1000

//если k = 0 и j == 0, то буква n millio n

//если только k = 0, то буква d тыс. d

//другой разумно использовать массив last_letters, поскольку

//единица цифр 1000, то есть k, не равна нулю

//для суммы чисел i, j, k - цифры номера базы 1000, поэтому

n = i*1000000 + j*1000 + k;

//представляем номер и используем

sum = n*(n+1)/2;

если вам нужно сделать это для номера, отличного от 51000000000, а затем рассчитать sums_sizes999 и использовать его естественным образом.

общая память: 0 (1000);

общее время: 0 (n), где n - число

Ответ 17

Это то, что я сделал бы:

  • Создайте массив из 2 997 строк: "один" через "девяностотничный", "onethousand" через "девяностотничный" и "onemillion" через "девяностотнинунемиллион".
  • Сохраните следующую информацию о каждой строке: length (это может быть вычислено, конечно), целочисленное значение, представленное строкой, и некоторое перечисление, чтобы указать, являются ли это "те", "тысячи" или "миллионы".
  • Сортировка по 2979 строк в алфавитном порядке.

При создании этого массива просто найти все 999,999,999 строк в алфавитном порядке на основе следующих наблюдений:

  • Ничто не может следовать за строкой "те"
  • Либо ни одна, ни "одна" строка может следовать за строкой "тысячи"
  • Ничего, ни одна строка, строка "тысячи" или строка "тысячи", а не "одна", могут следовать за "миллионной" строкой.

Построение слов в основном предполагает создание одно-трехбуквенных "слов" на основе этих 2,997 токенов, следя за тем, чтобы порядок токенов делал действительное число в соответствии с вышеприведенными правилами. Учитывая определенное "слово" , следующее "слово" выглядит следующим образом:

  • Увеличьте "слово" , добавив маркер в алфавитном порядке, если это возможно.
  • Если это невозможно сделать, продвиньте самый правый токен до следующего по алфавиту, если это возможно.
  • Если это тоже невозможно, удалите самый правый токен и, если это возможно, продвиньте второй правый крайний токен до следующего по алфавиту.
  • Если это тоже невозможно, все готово.

На каждом шаге вы можете рассчитать общую длину строки и сумму чисел, просто сохранив два текущих итога.

Ответ 18

Важно отметить, что существует много дублирующих и двойных подсчетов, если вы перебираете все 100 миллиардов возможных чисел. Важно понимать, что количество строк, начинающихся с "восьмерки", - это такое же количество чисел, которое начинается с "nin" или "seven" или "six" и т.д....

Для меня это требует решения динамического программирования, в котором количество строк для десятков, сотен, тысяч и т.д. вычисляется и хранится в некоторой таблице поиска. Конечно, будут специальные случаи для одного против одиннадцати, два против двенадцати и т.д.

Я обновлю это, если смогу быстро найти решение.

Ответ 19

НЕПРАВИЛЬНО!!!!!!!!! Я ПРОЧИТАЛ ПРОБЛЕМУ НЕПРАВИЛЬНО. Я думал, что это означает "какая последняя буква из последнего числа в алфавитном порядке"

что случилось с:

public class Nums {

// if overflows happen, switch to an BigDecimal or something
// with arbitrary precision
public static void main(String[] args) {
    System.out.println("last letter: " + lastLetter(1L, 51000000L);
    System.out.println("sum: " + sum(1L, 51000000L);
}    

static char lastLetter(long start, long end) {
   String last = toWord(start);
   for(long i = start; i < end; i++)
      String current = toWord(i);
      if(current.compareTo(last) > 1)
         last = current;

   return last.charAt(last.length()-1);
}

static String toWord(long num) {
   // should be relatively easy, but for now ...
   return "one";
}

static long sum(long first, long n) {
   return (n * first + n*n) / 2;
}
}

на самом деле не попробовали это:/LOL

Ответ 20

Я решил это на Java когда-то в 2008 году как часть приложения для работы в ITA Software.

Код длинный, и теперь, через три года, я смотрю на него с ужасом... Поэтому я не буду публиковать его.

Но я опубликую цитаты из некоторых заметок, которые я включил в приложение.

Проблема с этой головоломкой, конечно же, размер. Наивный подход заключался бы в сортировке списка в порядке номеров слов, а затем для итерации по отсортированным символам и суммированию списка. Со списком размером 999,999,999 это, конечно, займет довольно много времени, и сортировка, скорее всего, не будет выполнена в памяти.

Но в упорядочении есть естественные шаблоны, которые позволяют сочетать ярлыки.

Сразу же после любой записи (скажем, номер X), заканчивающейся "миллион", вы получите 999999 записей, начиная с того же текста, представляя все числа из X +1 к X + 10 ^ 6 -1.

Сумма всех этих чисел может быть вычислена по классической формуле ( "арифметический ряд" ), а счетчик символов может быть вычислен с помощью простой формулы, основанной на префиксе (X выше) и однократно вычисленном символе count для чисел от 1 до 999,999. Оба зависят только от "миллионной" части числа в базе диапазона. Таким образом, если количество символов для всего диапазона будет содержать весь счет ниже цели поиска, отдельные записи не должны проходить.

Подобные ярлыки применяются к "тысячам", и действительно могут быть применены к "сотне" или "миллиарду", хотя я не беспокоился о ярлыках на уровне сотен, а уровень миллиардов выходит за пределы этой проблемы.

Чтобы применить эти ярлыки, мой код создает и сортирует список из 2997 объектов, представляющих числа:

от 1 до 999 с шагом 1   1000 до 999000, шаг за шагом 1000   1000000 до 999000000, шаг за шагом 1000000

Этот код повторяется через этот список, накапливая суммы и количество символов, рекурсивное создание, сортировку и перемещение похожих, но меньших списков по мере необходимости.

Явный подсчет и добавление нужны только ближе к концу.

Я не получил работу, но позже использовал код как "образец кода" для другого задания, которое я получил.

Код Java, использующий эти методы, пропускает большую часть явного подсчета и добавления в течение примерно 8 секунд.