Не читается , 1830 1796 1791 1771 1762 1745 1736 1727 1626 1606 1577 байт
Вывод в обратном алфавитном порядке ( z
до a
), но в соответствии с вашими правилами, что представляется допустимым.
«" „“ „„„“ „“ „“““ „„„“““ „“»«»«„“ „“ „“ „“ „“»«»«»«»" „“ „“» «„„““» «» «„“„“„“» «» «„„“ „“ „“ „“ „““» «» "" „“ „“ „„„“ „“ „“““ «„„““» «„„“ „„„“ „“ „“““ „„„“““ „““» «» «» «» «" „“ „“ „“»" „“«"»«»«"„“„“„„„“„“„“““„„„“““» "„“„„„“„“„“„“““„“„“„“ «"»«»«„“»«»«„„“„“„““»«»«„“»«»«»«»«"„“» «„“„“„“„“"» «» «„“» «» «„“„“„“"»„“„“„“«"„“» "„“„“„“„“„„„“““" „„““«» «» «» «„“„“„“„„„“„„„“„“„“„“““„“„“„“““„“„“„“» «» "" „“ «» «» «„„“ „“ „“ „„„“““ „““» «„„““» «" „“ „“ „“»" „“ „“ „“ „„„“““ «» «„“» «» «» «» «„„“ „“ „“ „„„“““ „““» «» «» «„„““» «„„““»»«„„““» «„„““» «„„““» «„„““» «„„““» «„„““» «„„““» «„„““» "» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «" „“ „“ „„„“ „“ „“““»" «» «„“» «» «„„“ „“ „“ „““» «» «» «» «„“» «» «„“» «» «„„“ „““» «» "»«» «» «» «» «„„“ „“ „“ „““» «» «» «„„““» «» «„“» «» «» «» "" „“ „“ „“ «" „„„“““ „„„“““ „„„“““ „„„“““ „„„“““ „„„“““ „„„“““ "„„““ «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «»«"»«»«„“»«»«„“»«»«„“»«»«„“»«»«„“»«»«„“»«»«„“»«»"» «„„““» «„„““» «„„““» «„„““» «„„““» «„„““» «„„““» «„„““» "» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» '«» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «» «» "» «» «„“» «» «„“"»«"„“„“„“» «„“"»„“«"„“„“„„„“„“„“„“““„“» «» «„“„“„“„“» «» «„„“ „“ „“ „„„“““ „““» «» «„„“ „“ „““» «» "„“«» «» «„“» «» «" „“ „„„“ „“ „“““ „“ „“ „„„“““»" „“ „„„“ „“ „“ „“““ «» «» «» «„“» «» "„“„„„“““„„„“““„„„“““„„„“““„„„“““" „„““ «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «» «„“» «»«"»«»«„“»«»«„“»«»«„“»«»«„“»«»«„“»«»«„“»«»«„“»«»"» «„„““» «" „“ „“ „„„“ „“ „“““ „“ „“ „“»" „“ „„„“ „“ „“ „“““ „“ „“ „“ «" „“ „“ „“»«»«"„“„“„“„“„„„“„“„“„“““„“„“„“» "„“„“„“«» «„“„“„“„“» «» «» «» «» «„“„“„“„“» «» «» «» «» «„“„“„“„“» «» «» «» «» «„“„“„“„“» «» «» «» «„„“ „„„“ „“ „“““ „““» «" „“ „“ „“»" «» «„„“ „““» «» «» «„„““» «» «„“» «» «» «» «„„““» «» "„“„“„“«" "» „“ «" „“ „“»«„“ „“ „“ „„„“““ "» „“ «"»«„“ „“ „“ "» „“ „“ „“ " «„„“ „“ „““» «„„““» «» «„“» «» «» «» «„„““» «" „“»«» «„“» «» «„„““» «» «» «» «„“» «» "„“»«» «„“» «» «„„““» «» «» «» «„“» «» "„“»
объяснение
Во-первых, чтобы получить представление о том, что может сделать Unreadable, вот его основная операция:
- У вас есть бесконечная лента целочисленных ячеек произвольного размера
- Вы не иметь указатель памяти , как в Brainfuck; вместо этого вы разыменовываете ячейки по их расположению на ленте. Это означает, что вы можете «прочитать значение # 4» или «прочитать значение # (прочитать значение # 4)» (двойное разыменование).
- Вы можете только читать или записывать ячейки памяти (а не напрямую увеличивать / уменьшать, как в Brainfuck).
- Вы можете увеличивать / уменьшать значения в выражении. Таким образом, чтобы увеличить ячейку памяти , вы должны прочитать , приращение , запись , или иначе говоря:
write(x, inc(read(x)))
.
- Существуют циклы while и троичные условные выражения, которые могут проверять только ноль против ненулевого значения.
Эта программа использует ленту следующим образом. Имена переменных будут использованы в псевдокоде ниже. Кроме того, это документирует первую версию (которая была 1830 байтов); см. правки внизу, чтобы узнать, что изменилось с тех пор.
- Ячейка 0: переменная
q
- Ячейка 1: переменные
a
, p
,ch
- Ячейка 2: переменные
hash
,v
- Ячейка 3: переменные
b
,r
- Ячейка 4: переменные
aa
,l
- Ячейка 5: остается 0, чтобы отметить «конец» строки десятичных цифр
- Ячейки 6–95: сохранить строку десятичных цифр назад
- Ячейки 96–121: сохраняют количество голосов, которые будут удержаны пользователями
a
(96) - z
(121) (код ASCII буквы минус один).
- Ячейки 4657–7380: запомните, какие комбинации избирателей и избирателей встречались сколько раз. Эти ячейки имеют только 4 возможных значения:
0
= еще не видел, -1
= видел один раз, -2
= видел дважды, -3
= видел любое количество раз больше, чем 2.
Алгоритм по существу работает следующим образом:
- Продолжайте читать пары символов
a
и b
. Вычислите значение хеша (a-2)*(a-1)+b-1
, которое уникально для каждой комбинации букв a – z.
- Проверьте ячейку памяти на это значение хеша (
*hash
). Если это так -3
, пользователь уже имеет право на удаление голосов, так что увеличивайте *(b-1)
. В противном случае, уменьшить *hash
. Если это сейчас -3
, пользователь только что получил право на удаление голоса после трех вхождений, так что увеличивайте *(b-1)
на 3
.
- После этого пройдите через символы в обратном порядке (
z
до a
) и выведите те, которые требуют вычтенных голосов. Это требует ручного целочисленного деления на 10, чтобы перевести число в десятичные цифры.
После того, как все прояснилось, программа выглядит как псевдокод:
// Read pairs of characters
while (a = read) + 1 {
b = read
// Calculate hash = (a-1)*(a-2)/2 + b-1
// This also sets a = b-1
hash = 0
while --a {
aa = a
while --aa {
++hash
}
}
while --b {
++a
++hash
}
// If this combination has just been seen for the third time,
// increment *a by 3; if more than third time, increment *a by 1
*a = (*hash + 3) ? ((--*hash) + 3 ? *a : (*a+3)) : (*a+1)
}
// Loop through the characters z to a
l = 27
while --l { // l loops from 26 to 1 (not 0)
(v = *(ch = l + 95)) ? { // 'a' is ASCII 97, but cell 96
print (ch+1) // print the votee
// Now we need to turn the number v into decimal.
// p points to where we are storing decimal digits.
p = 5
while v {
// Integer division by 10 (q=quotient, r=remainder)
r = (q = 0)
while v {
--v
(++r - 10) ? 1 : {
r = 0
++q
}
}
// Store digit ASCII character
*(++p) = r + 48 // 48 = '0'
v = q
}
// Now output all the digit ASCII characters in reverse order
while *p {
print *(--p + 1)
}
} : 1
}
Изменить 1, 1830 → 1796: понял, что я могу повторно использовать возвращаемое значение цикла while в одном месте.
Edit 2, 1796 → 1791: Оказывается, программа немного меньше, если вместо использования ячеек 6–95 я сохраню десятичные цифры в ячейках с отрицательным номером (–1 и далее). В качестве дополнительного бонуса программа больше не ограничена 10⁹⁰ голосами!
Редактировать 3, 1791 → 1771: вместо присвоения результата *(ch = l + 95)
для v
я теперь присваиваю его, q
а затем перемещаю присвоение v = q
в условие while, переводя код в 1777 байт. Затем поменяйте местами расположение q
и v
на ленте, потому что q
теперь это на 1 чаще, чем v
.
Изменить 4, 1771 → 1762: Дух. Инициализация hash
до 1 вместо 0 на 9 байт короче. Хеш-код теперь на 1 больше, что не имеет значения.
Редактировать 5, 1762 → 1745: если я инициализирую q
и равным r
1 вместо 0, мне придется посыпать некоторые -1
s местами, чтобы все было правильно, и все это, похоже, отменяется - за исключением того, что while v { --v; [...] }
цикл теперь должен выполнить на одну меньшую итерацию, что я могу сделать, сказав while --v { [...] }
, что на 26 символов короче.
Изменить 6, 1745 → 1736: Вместо этого { r = 1; ++q }
мы можем написать q = *((r = 1)+1)+1
. Это зависит от того, что q
находится в переменной слот № 2. Если бы это было в слоте № 1, это было бы еще короче, но тогда вся программа была бы длиннее в целом.
Правка 7, 1745 → 1727: отменил правку 6 и вместо этого добился сохранения, вставив самый внутренний цикл while в выражение, которое вычисляет цифровой код ASCII, который также заканчивается 1736 байтами ... но затем сохранил инструкцию уменьшения (9 байтов). ), изменив ((++r) - 11) ? r :
на (r - 10) ? ++r :
.
Изменить 8, 1727 → 1626: переработан расчет хеша. Теперь он использует один цикл while. Местоположения ячеек теперь имеют свои действительные коды ASCII (больше не на 1). Перестановки переменных в разных местах на ленте, потому что они теперь происходят с различной частотой.
Изменить 9, 1626 → 1606: более сумасшедшее встраивание. Тело первого цикла while теперь выглядит примерно так:
// b = next char
*(b = (hash = read)) = {
// hash = b + (a-1)*(a-2)/2
while (a2 = --a) {
while --a2 {
++hash
}
}
// If this combination has just been seen for the third time,
// increment *b by 3; if more than third time, increment *b by 1
(*hash + 3) ? ((--*hash) + 3 ? *b : (*b+3)) : (*b+1)
}
и назначение переменных теперь почти полностью изменилось.
Edit 10, 1606 → 1577: Я заметил , что a
и a2
оба декрементируется 0 в то время как петли, так что, если я мог бы пару p
ни с одним из тех , кто, но не с ch
, я не должен был бы инициализировать p
до 0
(который стоит 29 байт). Оказывается, я могу сделать это путем обмена p
и r
. Новейшие назначения переменных (и их частота появления в коде) теперь:
0 = v (3) (total 3)
1 = hash (6), r (5), ch (2) (total 13)
2 = b (4), q (5) (total 9)
3 = a (3), p (5) (total 8)
4 = a2 (3), l (4) (total 7)
nanananananananabatman
теста.