Пора зайнятися математикою


14

Вступ

Це одна з моїх улюблених математичних головоломок.

Враховуючи цифру (скажімо 3) і кількість разів використовувати цю цифру (скажімо, 5), генеруйте 10 виразів, які призводять до 1, 2, 3, 4, 5, 6, 7, 8, 9 і 10, використовуючи просто +, -, ×, ÷, ^ і √ (корінь) (дужки дозволені до групових операцій).

Наприклад:

(3^3 + 3)/(3 + 3) = (33 - 3)/(3 + 3) = 3 + 3/3 + 3/3 = 5

Зауважте, що все вищезазначене використовує п'ять 3-х та математичні операції, а результат - 5. Ви також можете використовувати 3 перед √ для позначення куба куба. Те саме стосується використання 4 перед √ для позначення четвертого кореня.

Також зауважте, що два 3 можуть бути використані для формування 33, або три 3 можуть бути використані для формування 333 тощо.

Виклик

  • Вам будуть дані два числа (обидва - від 1 до 5) як аргумент функції, STDIN або аргумент командного рядка.
  • Перше число позначає, яку цифру слід використовувати, а друге число позначає кількість разів, яку цифра повинна використовувати в виразі.
  • Ваша програма повинна вивести масив розміром 10 (або 10 цифр, розділених пробілом), де кожен елемент позначає, чи можливий математичний вираз (використовуючи лише дозволені оператори), що призводить до (index + 1)числа, чи не використовує значення truthy / false.

Наприклад, якщо вхід є

1 3

Тоді вихід повинен бути

[1, 1, 1, 0, 0, 0, 0, 0, 0, 1]

тому що лише 1, 2, 3 і 10 можна виразити за допомогою трьох 1.

Оцінка

  • Це тому мінімальна довжина коду в байтах виграє.

Бонус

Print-em-all [−50]

Відніміть 50 з вашої оцінки, якщо вихідний масив елементів дорівнює загальній кількості правдоподібних комбінацій, щоб отримати (index + 1)значення замість правдоподібних або хибних значень.

Наприклад, якщо є лише 3 можливі комбінації з п'яти 3, які приводять до 5, то 4- й запис вихідного масиву повинен бути 3.

Екстремальна математика [−100]

Відніміть 100 з вашої оцінки, якщо елементи вихідного масиву містять принаймні один із фактичних виразів, що призводять до (index + 1)значення.

Наприклад, якщо використовується п'ять 3-х, 4- м записом вихідного масиву може бути або (3^3 + 3)/(3 + 3), (33 - 3)/(3 + 3)або3 + 3/3 + 3/3

Перенаселений [−200]

Відніміть 200 з вашої оцінки, якщо елементи вихідного масиву містять усі можливі комбінації (розділені на |). Цей бонус додається на додаток до бонусу Extreme Maths , так що ви отримуєте −300 в цілому.

Наприклад, якщо використовується п'ять 3-х, 4- й елемент вихідного масиву повинен бути(3^3 + 3)/(3 + 3)|(33 - 3)/(3 + 3)|3 + 3/3 + 3/3

Примітка: Будь-які два вирази для досягнення одного результату повинні бути логічно різними при різному підході в обох.

Наприклад, отримати 5, використовуючи п'ять 3-х, те 3 + 3/3 + 3/3саме 3/3 + 3 + 3/3або 3/3 + 3/3 + 3тому, що для кожного з них застосовується однаковий підхід. (3^3 + 3)/(3 + 3)і (33 - 3)/(3 + 3)відрізняються, оскільки 30 у чисельнику досягається за допомогою різних підходів.

ОНОВЛЕННЯ : Після перегляду всіх відповідей було встановлено, що всі відповіді мали недосконалість через крайні випадки одинарності -та √. Таким чином, відсутність цих кращих справ вважалася нормальною, що стосується повноти відповідей.

Це складне питання, але досить цікаве.

Щасливого гольфу!


1
Вибачте, це може бути німим, але як ви отримуєте 10 лише з трьома 1с?
FryAmTheEggman

3
@FryAmTheEggman 11-1
оптимізатор

1
Ах, так я був тупий: p
FryAmTheEggman

4
Це дуже розпливчасте правило. Я можу вирішити, що квадратний корінь 1, квадратний корінь квадратного кореня 1 і т.д. - це всі різні підходи, і я маю нескінченну кількість відповідей. Чи а + b відрізняється від b + a? Чи відрізняється (-a) * (-b) від b * a?
feersum

2
Мені це відомо, але я не можу представляти 4 ^ (4 ^ (4 ^ (4 ^ 4))) у будь-якому форматі звичайного числа - для зберігання 4 ^ (4 ^ (4 ^ 4)) як ціле число вже потрібно більше біт ніж у Всесвіті є атоми). Тому, якщо я не використовую систему комп’ютерної алгебри, здатну обробляти такі числа (якщо така існує взагалі), мені потрібно ставитися до них як до особливих випадків. Це, однак, майже напевно вимагає більше символів, ніж я виграю через перевищення рівня. Тому ці нагороди безглузді, якщо ви дещо не виключаєте численні квадратні корені.
Wrzlprmft

Відповіді:


1

Пітон 3 (недосконалий), 449 - 300 = 149

Страждає від тих самих недоліків, що і рішення KSab : жодні одинарні оператори, повністю скоплені в скобках, не містять еквівалентних виразів, таких як (1+1)+1і 1+(1+1). Я усунув точні дублікати, передавши результати до set(). Вихід може бути трохи потворнішим, щоб зберегти кілька байт, але мені це подобається таким чином. Я також не робив nth коріння, тому що, здається, вони купують тебе багато в цій проблемі.

R=range
E=lambda z:eval(z.replace("^","**"))
def m(d,n):_=R(1,11);s={i:[]for i in _};r=R(1,n);n<2 and s[d].append(str(d));d=str(d);t=[[(d*i,i)for i in r]]+[[]]*n;h=[];[(h.append("("+A+o+B+")"),t[l].append((h[0],a+b))if a+b<n else E(*h)in _ and s[E(*h)].append(h[0]),h.pop())for l in r for j in R(l)for A,a in t[j]for k in R(l)for B,b in t[k]if a+b<=n for o in"+-*/^"if(o=="^"and-~-(0<E(B)<9)or 0==E(B)and"/"==o)-1];[print(i,set(s[i])or'')for i in _]

Якщо другий аргумент дорівнює 5. Тестування займе кілька хвилин, зателефонувавши m(digit, number):

>>> m(1,3)
1 {'((1*1)^1)', '(1^(1+1))', '((1-1)+1)', '((1/1)/1)', '((1*1)*1)', '((1^1)/1)', '(1*(1*1))', '(1^(1*1))', '(1+(1-1))', '(1^(1^1))', '((1^1)*1)', '(1^(1/1))', '((1/1)*1)', '(1-(1-1))', '(1/(1^1))', '(1/(1*1))', '(1/(1/1))', '(1*(1^1))', '((1+1)-1)', '((1*1)/1)', '((1^1)^1)', '(1*(1/1))', '((1/1)^1)'}
2 {'(1*(1+1))', '((1^1)+1)', '((1+1)/1)', '((1*1)+1)', '((1+1)^1)', '(1+(1*1))', '((1/1)+1)', '(1+(1^1))', '(1+(1/1))', '((1+1)*1)'}
3 {'((1+1)+1)', '(1+(1+1))'}
4 
5 
6 
7 
8 
9 
10 {'(11-1)'}
>>> m(3,3)
1 {'((3/3)^3)'}
2 {'(3-(3/3))', '((3+3)/3)'}
3 {'(3-(3-3))', '((3-3)+3)', '((3/3)*3)', '(3*(3/3))', '(3/(3/3))', '((3+3)-3)', '(3^(3/3))', '(3+(3-3))', '((3*3)/3)'}
4 {'((3/3)+3)', '(3+(3/3))'}
5 
6 {'((3*3)-3)'}
7 
8 
9 {'(3+(3+3))', '((3+3)+3)', '((3^3)/3)'}
10 

4

Пітон (недосконалий) 493 474 - 300 = 174

З цим рішенням існує досить багато питань, по-перше, він ігнорує будь-який надмірний показник (будь-який, у якого показник більше 100). Я насправді не думаю, що це не усуває будь-яких можливостей для введення, менших або рівних 5, але я не впевнений на 100%.

Інша справа, що він не враховує жодних одинарних квадратних коренів, оскільки він би ускладнився (будь-яке рішення з будь-яким терміном, рівним 0 або 1, дало б нескінченну кількість рішень). Він також не враховує жодної одинарної заперечення (символ "-") з тієї ж причини, а також того, що я не впевнений, чи задавали це питання.

Я також розглядав, які критерії повинні вирішувати, якщо два вирази є рівнозначними, але я не міг знайти спосіб суворо визначити це таким чином, як мені здалося, інтуїтивно зрозумілим, тож (поки що принаймні) я нічого подібного не реалізував. Це означає, що він дає досить багато результатів, а також використовує дужки досить наївно.

Зі сторони, я думаю, що це може включати найдовший єдиний рядок коду, який я написав, особливо до того, як він був повністю гольф.

R=range
F=lambda s:lambda a,b:eval(s)
L=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)|(b>99)else a**b")),('v',F("b**(1./a)if a and(a>=0 or b)and(b>=0 or int(1./a)==1./a)&(1./a<99)else''"))]if o(u,v)!='']
A=L(*input())
for i in R(11):
 for v,s in A:
    if v==i:print i,s[1:-1]

Приклад: ('v' означає '' ')

2,3

0 2*(2-2)
0 2v(2-2)
0 (2-2)*2
0 (2-2)/2
0 (2-2)^2
1 2^(2-2)
1 2-(2/2)
1 2v(2/2)
1 (2/2)^2
2 2v(2+2)
2 2+(2-2)
2 2-(2-2)
2 2v(2*2)
2 2*(2/2)
2 2/(2/2)
2 2^(2/2)
2 2v(2^2)
2 (2+2)-2
2 (2+2)/2
2 (2-2)+2
2 (2*2)-2
2 (2*2)/2
2 (2/2)*2
2 (2/2)v2
2 (2^2)-2
2 (2^2)/2
3 2+(2/2)
3 (2/2)+2
6 2+(2+2)
6 2+(2*2)
6 2+(2^2)
6 (2+2)+2
6 (2*2)+2
6 (2^2)+2
8 2*(2+2)
8 2*(2*2)
8 2*(2^2)
8 (2+2)*2
8 (2*2)*2
8 (2^2)*2

Я знайшов пару речей, які ви можете зробити, щоб скоротити L:L=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)or b>100 else a**b")),('v',F("''if a==0 or(b<0 and int(1./a)!=(1./a))or(b or a<0)or(1./a)>100 else b**(1./a)"))]if o(u,v)!='']
FryAmTheEggman,

Вибачте, цей коментар виглядає дуже погано :( У всякому разі, для пояснення: порівнюючи проти 0, я намагався заперечити твердження, а потім змінити наслідки. Я також знайшов кілька місць для використання, |а &не orі and. Обидва ці хитрощі можна було використати для скорочення останнього дзвінка на F, але для цього знадобиться Деморган, і у мене закінчився час дзьоба; p
FryAmTheEggman

@FryAmTheEggman О, це гарна уловка, я оновив свою відповідь тим, що ви розмістили, і коли встигну, я перегляну останній. Ці умови, щоб перевірити обґрунтованість введення, отримали трохи більш здоровенний, ніж я очікував: /
KSab

+10 для блискучості вкладених лямбдашів eval- це знадобило мені достатньо часу, щоб визначити ваш другий рядок! Я думаю, що я тебе змусив бити на "найдовшій одиночній лінії". ;) Я згоден на ігнорування великих експонентів; насправді, я думаю, що будь-який показник, більший за 9, не стане корисним (за винятком випадків, коли базовий показник становить 1).
DLosc

@DLosc Ну, один сценарій, який ти можеш мати, є щось на кшталт 3 = 33 √ (3 ^ 33). Насправді, коли я це пишу, я розумію, що дві (мабуть, єдині дві?) Комбінації, які моя відповідь не вистачає, 4 = (4^4) √ (4 ^ (4^4))і еквівалентний вираз з 5s. Справді, коріння, здається, не створюють особливих проблем, оскільки переважна більшість з них використовується або як відсутнє або 0, або 1, без опісу, коли корінь дорівнює 1, або просто для відміни живлення.
KSab

3

Пітон 3 - 349 346

r=range
l=lambda s:eval("lambda a"+s)
def T(u,f,X,Y):
    try:return u(f(X,Y))
    except:0
c=l(',x:{x}.union(*[{u(int("1"*a)*x)}|{T(u,f,X,Y)for j in r(1,a)for X in c(j,x)for Y in c(a-j,x)for f in[l(",b:a%sb"%o)for o in{"**"}|set("+-*/")]+[l(",b:a**b**-1")]}for u in[l(":-a")]+[l(":a**.5**%i"%k)for k in r(9)]])')
R=l(",i:[{n+1}<c(i,a)for n in r(10)]")

Ось доволі неопущена версія:

def R(x,i):
    # Unary Operations
    U = [lambda a:-a] + [eval("lambda a:a**(1/2.**%i)" % j) for j in range(9)]
    # Binary Operations
    F = [eval("lambda a,b:a%sb"%o) for o in ["+","-","*","/","**"]] + [lambda a,b:a**(1./b)]

    def combos(i):
        L = {x}
        for u in U:
            # 3, 33, 333, etc.
            L |= {u(int(str(x)*i))}

            for j in range(1,i):
                for X in combos(j):
                    for Y in combos(i-j):
                        for f in F:
                            # To avoid trouble with division by zero, overflows and similar:
                            try:
                                L |= {u(f(X,Y))}
                            except:
                                pass
        return L

    return [n in combos(i) for n in range(1,11)]

Для тестування рекомендую перейти (9)на щось менше, оскільки це враховується кількість множинних квадратних коренів, що має величезний вплив на продуктивність.

Нарешті, це змусило мене замислитися, чи потрібен унарний мінус в деяких випадках…


1
Я думаю, ти маєш рацію щодо унарного "-", ймовірно, нічого не додавши (принаймні до базового питання без бонусів). Єдиним нетривіальним сценарієм, про який я можу придумати, було б щось подібне 1 = 3^3 * 3^(-3), але навіть враховуючи це, я сумніваюся, що є якісь цифри, для яких це можливе рішення, коли інших немає.
KSab

1
Ви можете зберегти 3 байти, використовуючи a**.5**%iзамість a**(1/2**%i)обчислення кількох квадратних коренів.
DLosc

@DLosc: Дійсно, дякую.
Wrzlprmft

Можна зберегти шість байтів, зменшивши чотири пробіли до одного пробілу.
Бета-розпад

@BetaDecay: Я ніколи не використовую чотири пробіли (здригаються), я використовую вкладки. Просто загляньте в джерело моєї публікації. Обмін стеками просто відображає їх як чотири пробіли.
Wrzlprmft

2

Mathematica - 246 символів (бонуси не заявлені)

f[x_,y_]:=x-y
g[x_,y_]:=x/y
h[x_,y_]:=x^(1/y)
j[x_,y_]:=FromDigits@Join[IntegerDigits@x,{y}]
z[{r_,n_,L_}]:=z[{L[[1]][r,n],n,Rest@L}]
z[{r_,n_,{}}]:=r
a[n_,t_]:=Union@Select[z[{n,n,#}]&/@Tuples[{Plus,f,Times,g,Power,h,j},t-1],IntegerQ@#&&0<#<11&]

Пояснення

Функція jпоєднує два числа в цифрах.

Функція zприймає результат r, число nта список функцій L, кожна з яких працює на двох аргументах. Потім він послідовно застосовує список функцій до аргументів [r,n]за допомогою рекурсії, поки список не буде порожнім, після чого він поверне результат.

Функція aзаймає кількість nта кількість копій t. Він створює всі кортежі довжиною (t-1) зі списку функцій {Plus, f, Times, g, Power, h, j}і надсилає кожен кортеж через функцію z, а потім повертає список усіх чисел 1 до 10, які були створені.

Приклад виконання a[2,3]повернення {1, 2, 3, 6, 8}.

Обмеження

Оскільки список функцій застосовується послідовно, щоразу використовуючи одну копію числа, він може пропустити деякі комбінації. Наприклад, при роботі на чотирьох двіях він пропустив би 22/22 = 1 через неможливість оцінювати список функцій не в порядку. Звичайно, 2/2 * 2/2 = 1 охоплює цю справу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.