Pull to refresh
2
0.1
Send message

Немного идей к лучшим решениям на Python:

Ёлочка (61)

Решение из статьи:

n=int(input())
for i in [*range(n),1]:print(' '*(n-i)+'*'*(2*i+1))

Вместо списка можно генерировать кортеж, да и пробел там не нужен (минус 3 символа):

n=int(input())
for i in*range(n),1:print(' '*(n-i)+'*'*(2*i+1))

Вместо 2*i+1 можно написать простое и понятное i-~i. Впрочем, в данном конкретном случае можно сэкономить символ проще:

n=int(input())
for i in*range(n),1:print(' '*(n-i)+'*'+'**'*i)

Наконец, символ можно отыграть моржовым оператором:

for i in*range(n:=int(input())),1:print(' '*(n-i)+'*'+'**'*i)
Обратный отсчет (174)

Решение из статьи:

p=print
for i in range(int(input()),0,-1):p('До Нового года остал'+"оссяь"[i<2::2],i,f'д{"неннненяяяйь"[i*(i<5)::5]}!')
p('С Новым годом!')

Если приходится передавать в range несколько аргументов, то почти всегда короче переписать на while (минус 6 символов):

p=print
i=int(input())
while i:p('До Нового года остал'+"оссяь"[i<2::2],i,f'д{"неннненяяяйь"[i*(i<5)::5]}!');i-=1
p('С Новым годом!')

Строка "ня" закодирована 3 раза. Хочется подобрать выражение, которое будет переводить числа 2, 3, 4 в одно значение (минус 5 байт):

p=print
i=int(input())
while i:p('До Нового года остал'+"оссяь"[i<2::2],i,f'д{"енннеяьй"[1%i<<(i<5)::3]}!');i-=1
p('С Новым годом!')

Она [задача «Переставлюн»] создавалась как задача, которую на С++ будет решить короче, чем на Python.

Переставлюн (90)

Генерируем перестановки, пока не встретится поданная на вход, выводим следующую:

from itertools import*
s=*input(),
p=permutations(sorted(s))
s in p
print(*next(p),sep='')

Если необходимо поддержать поведение std::next_permutation, который из последней перестановки делает первую, то получается 95 символов:

from itertools import*
s=*input(),
p=permutations(t:=sorted(s))
s in p
print(*next(p,t),sep='')

Но у этих решений есть небольшая проблема с асимптотикой...

Функцию list можно заменить на синтаксис списка:

c = list(map(int, s))  # 18, пример из статьи
c = [*map(int, s)]  # 15
*c, = map(int, s)  # 14

Если join подаётся на print, то можно и использовать print, заодно пропадёт необходимость в строковости:

s = [1,2,3,4,5,6]
print(''.join(s))  # 17, нерабочий пример из статьи
print(*s, sep='')  # 16

У тернарника есть еще несколько вариантов, которые могут оказаться полезны:

print('A' if a==b else 'B')  # 23, пример из статьи
print(a==b and 'A' or 'B')  # 22
print((a==b) * 'A' or 'B')  # 22

Что касается финального решения в 34 символа через пробелы, то на acmp.ru изменили функцию подсчёта длины кода именно для борьбы с такими решениями:

[Размер кода] = max([длина кода без пробелов, табуляций и символов перевода строки], [полная длина кода, делённая нацело на 4])

Насколько любые?
Можно написать sinh(1) + cosh(3-2) + 0*(4+5+6+7+8+9) и получить точное значение числа e.
Если позволить факториал, то можно получить сколь угодно близкое к числу e значение, добавляя новые факториалы вокруг (4+5+6) и (7+8):
(1+(3-2)/(4+5+6)!)^(7+8)! + 0*9.
Если использовать степени, то лучшее, что мне удалось найти, это
(1+3^(-2^85))^(9^(4^(6*7))) + 0
Это приближение даёт примерно 1.846*10^25 правильных знаков числа e.
Ещё есть: 000000, 000001, 000002, ..., 000099.
Всего решений нет у 93265 билетов. Если требовать расставить знаки во всех 5 местах, то решений нет у 283730 билетов.
Год назад на хабре уже заходила речь об этой игре, тогда я подсчитал общее количество счастливых таким образом билетов, а заодно попытался сгенерировать наиболее сложные билеты. Если кому-то хочется поломать голову, привожу их список по возрастанию сложности (по моему субъективному мнению). Но в известной мне версии игры необязательно ставить знаки между всеми цифрами, то есть для билета 777777 допустимым решением является (777-77)/7, в примерах это используется.
101048
(10+10/4)*8

399940
(3-9/(9+9))*40

146778
(14-6/7)*7+8

198797
1-9*(8/(7-9)-7)
Или факториал:
4!*2*2+4+0+0
Перебор подтверждает, что решений нет.
Закодил перебор. Если нигде не ошибся, то счастливыми являются 906735 билетов. Так что результат 10 из 10 кажется не сильно удивительным. Но, если честно, я поражён, что у вас так легко получилось. Порой я убивал всю поездку, чтобы найти сотню. Поэтому попробовал специально поискать сложные билеты (сам билет в заголовке спойлера, ответ внутри):
101048
(10+10/4)*8

399940
(3-9/(9+9))*40

146778
(14-6/7)*7+8

198797
1-9*(8/(7-9)-7)

Я постарался отсортировать их в порядке возрастания сложности.

P.S. Если запретить использовать многозначные числа (то есть требовать расставить все 5 знаков), то счастливых билетов остается 716270.
Есть известная вариация: расставляя знаки арифметических действий и скобки, получить в результате 100. Знаки само собой не обязательно расставлять между всеми цифрами, то есть для билета 777777 допустимым решением является (777-77)/7. Решения есть для значительной доли билетов (если мне не изменяет память, по опыту выходило где-то треть или половина), но зачастую очень хитрые.
А компьютер умеет понимать контекст и опознавать каламбуры?

Контекст — это локальные знания, то есть знания, полученные из предыдущих предложений. Для понимания контекста нужно просто хранить и использовать эти знания (давать им более высокий приоритет, чем глобальным знаниям).
Как понимать каламбуры, я написал выше: «оба варианта являются предпочтительными (причём по разным причинам)».

В чем же тогда вообще проблема с машинным распознаванием текстом?

Я вижу две проблемы:
1) Сложность естественных языков, битком набитых правилами и исключениями из этих правил, то есть проблема парсинга текста естественного языка в некую структуру, пригодную для анализа.
2) Компьютер не обучается естественно и не накапливает ту колоссальную базу знаний о мире, которая есть у человека: что является едой, что является человеком, какие есть устойчивые выражения и так далее.

Решение обоих проблем требует чудовищных усилий по созданию соответствующих баз и алгоритмов (чем сейчас и занимаются вроде), которые всё равно будут постоянно устаревать. Поэтому, мне кажется, единственным удовлетворительным решением этой проблемы будет использование самообучающегося ИИ, с созданием которого человечество пока не преуспело.
В качестве временного решения используют уже ставшее привычным «завалим компьютер огромным количеством данных: пусть он в них ищет наиболее подходящее и действует по аналогии», что избавляет компьютер от необходимости понимать, что он делает. Как показывает пример Google Переводчика, работает данное решение неудовлетворительно, но зато оно относительно просто и универсально.
Да, всё еще просто. Тут опять же зависит от того, к какому слову относится «с друзьями». Так как оба варианта являются предпочтительными (причём по разным причинам), то без дополнительного контекста компьютер не может понять, какой из них верен. И решит, что это выражение является каламбуром. Так же как и человек.
С точки зрения языка как-раз таки всё просто: «с грибами» относится к «пирожки», а «с друзьями» — к «я». Возможное рассуждение компьютера:
1) «с грибами» относится к «ел» (грибы отдельно от пирожков) или «пирожки» (грибы внутри пирожков), так как эти слова одной тематики «еда». У «пирожки» приоритет выше, потому что в реальности часто встречаются объекты «пирожки с грибами».
2) «с друзьями» относится к «я», так как это термины одной категории «люди».
3) «с котятами» относится без понятия куда. Компьютер вероятно отнесет их к «пирожки», сочтя это устойчивым выражением. Без контекста всё это рассуждение является чепухой, потому что повествование вполне может вестись от лица кота: тогда «я» и «котята» будет принадлежать к одной категории «коты» и компьютер поймет, что «с котятами» относится к «я».

Information

Rating
4,032-nd
Registered
Activity