Виведення вираження, що не підтверджує основу


21

Фон

У деяких можливих ф’ючерсах світ перетворить свої числові системи з десяткових (основа 10 або b10) в якусь іншу базу (двійкову b2, восьмеричну b8, шістнадцяткову b16чи навіть одинарну b1, і в цьому випадку ми їх накрутили!). Таким чином, готуючись до цієї можливої ​​світової події, ви вирішили базувати всі свої програми. Це можна зробити, використовуючи лише сингулярні 0s і 1s спільно з операторами для заміни існуючих констант чисел.

Однак є лише одна проблема: у вас є багато програм, щоб змінити, і вручну конвертувати кожне число у вираз буде потрібно тижнів! Таким чином, ви вирішили написати програму (або функцію), щоб вирішити для вас, який вираз повинен замінити кожне число.

Вхідні дані

Вхідним числом буде додатне ціле число. Ваш код повинен мати можливість обробляти будь-яке ціле число до 1000.

(Якщо ваш код підтримує десяткові знаки та / або негативні введення, див. Підрахунок нижче.)

Вихідні дані

Ваш код повинен виводити вираз, який оцінює вхід принаймні однією мовою. Це може бути будь-яка мова; воно не повинно бути таким самим, як написано у вашій програмі чи функції. Також цей вираз не повинен бути повноцінною програмою чи функцією.

Для наочності вихід може містити будь-яку з цих операцій:

  • приріст / декремент
  • додати / суму
  • відняти / заперечити
  • помножити / подвоїти (лише якщо це не включає безпосередньо число 2!)
  • ділити / модуль
  • експоненти / логарифми
  • квадрат / sqrt (знову ж таки, лише якщо вони безпосередньо не включають число 2!)
  • побітові операції (bOR, bAND, bNOT, bXOR, bit-shift)
  • налаштування / отримання змінних
  • маніпуляція стеком

Ви не можете використовувати eval()або подібні функції у виході. Ви також можете не використовувати у висновку будь-які функції, які виконують дії, відмінні від зазначених вище.

О, і ще одне: оскільки ми хочемо, щоб результат був дійсним у якомога більшій кількості баз, єдине число констант, яке воно може містити, є 0і є 1. Числа, такі як 10(десять), заборонені, якщо мова не трактує це як a 1і a 0. Використання рядків для розміщення чисел також не дозволено, як і використання символів, таких як CJam's A- K(які представляють 10- 20).

Тестові кейси

(Усі виходи знаходяться в JavaScript, але можуть працювати іншими мовами.)

Введення 1:

2

Можливий вихід 1:

1+1

Введення 2:

13

Можливий вихід 2:

(a=1+1+1)*a+a+1

Введення 3:

60

Можливий вихід 3:

(b=(a=1+1+1+1)*a)*a-a

Введення 4:

777

Можливий вихід 4:

(c=(b=((a=1+1+1+1)*a-a+1)*a)*a+b)+c+c-a+1

Введення 5:

1000

Можливий вихід 5:

Math.pow((a=1+1+1)*a+1,a)

Оцінка балів

Мета цього завдання - максимально скоротити вихід коду. Ваша оцінка буде розрахована таким чином:

  • Базова оцінка: середнє число байтів для всіх виходів для цілих чисел від 1 до 1000.

  • Десяткова оцінка: Якщо ваш код підтримує щонайменше 3 десяткових знаки, це середній байт-кількість усіх результатів послідовності чисел, що починаються з 0.001та закінчуються на 1000, збільшуючись з 1.001кожним разом. 0.001, 1.002, 2.003...998.999, 1000.000Потім зніміть 50% від цієї оцінки.

  • Негативний бал: Якщо ваш код підтримує від’ємні числа і нуль, це середній байт-кількість результатів усіх цілих чисел від -1000до 0. Потім зніміть 10% від цієї оцінки.

(Найпростіший спосіб їх обчислення, швидше за все, буде циклом із програмою / функцією всередині.)

Ваш остаточний бал - це середнє значення, залежно від того, що стосується наведених формул.

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

Крім того, оскільки ви не знаєте, якими будуть дорогоцінні комп'ютерні дані в майбутньому, кількість байтів вашого генераторного коду має бути менше 512 байт.

Найменший бал за два тижні (30 вересня) буде оголошено переможцем. Вітаємо переможця, @ThomasKwa !


Таблиця лідерів

Щоб переконатися, що ваша відповідь відображається правильно, почніть її з цього заголовка:

# Language name/Other language name, X points

Де Xоцінка вашої відповіді. Приклад:

# CJam/Pyth, 25.38 points

Якщо у вас є якісь питання або пропозиції, будь ласка, повідомте мене про це. Удачі!


Чи можу я використовувати змінні, які містять 0чи 1за замовчуванням?
Денніс

@ Денніс Я не бачу жодної проблеми з цим, тому продовжуйте!
ETHproductions

Я припускаю, що я не можу здійснити перетворення бази між базовою 2 та базовою за замовчуванням.
Синій

@muddyfish Ні, у виході не дозволено перетворення бази.
ETHproductions

Гадаю, нам теж не дозволяється використовувати щось подібне Integer.parseInt("1000", 1+1+1+1+1+1+1+1+1+1)? Я впевнений, що parseIntвикористовує лише дозволені операції ;-)
Paŭlo Ebermann

Відповіді:


10

Код машини Python / Zilog Z80, 11.653 11.488

import math,numpy as np
def R(n):
    if n==0:return []
    if n<0:return -R(-n)
    e=int(math.log(n,2))
    if n >= 5/3 * 2**e:
        return np.append(2**(e+1),-R(2**(e+1)-n))
    return np.append(2**e,R(n-2**e))

def strR(n):
    b = R(n)
    s = ""
    if n==0:return s
    e=max(abs(b))
    while e:
        if e in b:s+="#"
        elif -e in b:s+="+"
        s+=")"
        e//=2
    return s[:-1]

Бонуси: Негативні номери.

Передбачається, що hlпара реєстру спочатку містить 0 і повертає результат у hl.

Використовуються лише ці три інструкції:

ASCII   Hex    Instruction
--------------------------
#       23     inc hl
)       29     add hl,hl
+       2B     dec hl

Ми використовуємо невелику модифікацію збалансованого бінарного представлення з мінімальною вагою BBR2 . Оскільки BBR2 мінімізує вагу (кількість ненульових цифр), але ми хочемо мінімізувати вагу плюс кількість бітових зрушень, ми змінюємо константу в алгоритмі з 3/2на 5/3.

Для обчислення балу та перевірки використовуйте цей код:

def verify(n):
v = 0
for c in strR(n):
    if c=="#":v += 1
    elif c=="+":v -= 1
    else: v *= 2
return v==n

print(0.5*(sum([len(strR(n)) for n in range(1,1001)])/1000 + \
           sum([len(strR(n)) for n in range(-1000,1)])/1001 * 0.9))

print(all([verify(n) for n in range(-1000,1001)]))

Приклад виводу:

strR(486)
         '#)))))+)+))+)'

Або в зборі:

inc hl \ add hl,hl \ add hl,hl \ add hl,hl \ add hl,hl \ add hl,hl \ dec hl \ add hl,hl \ dec hl \ add hl,hl \ add hl,hl \ dec hl \ add hl,hl

Ще приклади програм:

-256  +))))))))
-255  +))))))))#
-254  +)))))))#)
-253  +)))))))#)#
-252  +))))))#))
-251  +))))))#))#
-250  +))))))#)#)
-249  +)))))#)))+
-248  +)))))#)))
-247  +)))))#)))#
-246  +)))))#))#)
-245  +)))))#))#)#
-244  +)))))#)#))
-243  +)))))#)#))#
-242  +))))#)))+)
-241  +))))#))))+

  -5  +))+
  -4  +))
  -3  +)+
  -2  +)
  -1  +
   0  
   1  #
   2  #)
   3  #)#
   4  #))
   5  #))#

Можливі оптимізації: ОР правила, що inc hта dec hінструкції, що безпосередньо змінюють верхній байт hl, є незаконними, але sla hі недокументовані sl1 h(лівий біт зміщується на 1 на hцей зсув в а 0і 1відповідно) дозволені. sla hі sl1 hмають два байти кожен, але вони можуть іноді скоротити вихід.


Дуже приємно, найнижчий поки що! Я думаю, це один із випадків, коли чистий машинний код стане в нагоді. ;)
ETHproductions

2
+1 це, мабуть, неперевершено. Також для генія використання машинного коду (на процесорі з 8-бітовим набором інструкцій та 16-бітових регістрів.)
Level River St

Дивно, як це +перекладається dec. Я продовжую читати негативні приклади неправильно.
ETHproductions

9

CJam / CJam, 143.263 42.713 28.899 23.901 21.903 20.468

ri
[
    ['X\2b1>e`{~{"1)*)"*}{_({(')*1\"m<"}{"1)*"*}?}?}/]s
    "X1)*"/"1)"*
    "1)1)*"/"1)))"*
    "X1)m<"/"1)))"*
    _"1)"/("1):Y"+\'Y*+
]
{,}$0=

Бонуси не застосовуються.

Спробуйте в Інтернеті: зразок запуску | оцінка калькулятор | перевірка

Приклад виконання

   1 X
   2 1)
   3 1))
   4 1)))
   5 1))))
   6 1))1)*
   7 1))1)*)
   8 X1))m<
   9 1)))1)*)
  10 1))))1)*
  11 1))))1)*)
  12 1))1)m<
  13 1))1)*1)*)
  14 1))1)*)1)*
  15 1))1)*)1)*)
  16 X1)))m<
  17 X1))m<1)*)
  18 1)))1)*)1)*
  19 1)))1)*)1)*)
  20 1))))1)m<
 981 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*Y*)
 982 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*)Y*
 983 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*)Y*)
 984 1):Y)Y*)Y*)Y*Y*)Y*)Y)m<
 985 1):Y)Y*)Y*)Y*Y*)Y*)Ym<Y*)
 986 1):Y)Y*)Y*)Y*Y*)Y*)Y*Y*)Y*
 987 1):Y)Y*)Y*)Y*Y*)Y*)Y*Y*)Y*)
 988 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Ym<
 989 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*Y*)
 990 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*)Y*
 991 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*)Y*)
 992 1):Y)Y*)Y*)Y*)Y)))m<
 993 1):Y)Y*)Y*)Y*)Y))m<Y*)
 994 1):Y)Y*)Y*)Y*)Y)m<Y*)Y*
 995 1):Y)Y*)Y*)Y*)Y)m<Y*)Y*)
 996 1):Y)Y*)Y*)Y*)Ym<Y*)Ym<
 997 1):Y)Y*)Y*)Y*)Ym<Y*)Y*Y*)
 998 1):Y)Y*)Y*)Y*)Ym<Y*)Y*)Y*
 999 1):Y)Y*)Y*)Y*)Ym<Y*)Y*)Y*)
1000 1):Y)Y*)Y*)Y*)Y*Y*)Y)m<

Моє слово, це було швидко! Однак посилання не працюють у Firefox.
ETHproductions

Оскільки це не код гольфу, я замінив кожного %на більш тривалий вираз. Посилання мають працювати зараз.
Денніс

Вхід 34 дає 1. На якому вході він працює краще
Kishan Kumar

2
@KishanKumar Підтвердження перевіряє всі 1000 можливих входів. Вихід 1 вказує на те, що порівняння було успішним.
Денніс

Чи можете ви додати кілька прикладних результатів?
Paŭlo Ebermann

3

ß / BrainFuck, 34.201 балів

ß- джерело (194B):

E='++[------>+<]>++'°\c[1]<0°{E&='.'µA=ß"-ß°°c[1]),'')µE&='+++'°/B=1°(A[0]°\A[B]='.'°{µE&='--.++'°]E&=ß~A'+',A[B])&'.'&ß~A'-',A[B])°}°)°'ß"&E,'+-')+ß"&E,'-+')>0µE=ß"'ß"'E,'-+',''),'+-','')°!€E)

Якщо когось цікавить, я додам пояснення. Вихід BF вже досить оптимізований, але, мабуть, я міг би використати решту 318B коду ß для реалізації

  • оптимізація циклу вкладання,
  • більше 8-бітових ярликів переповнення,
  • зняття зіткнення оператора .

Зразки:

Запуск у Windows:

$ sharps encode.ss 42
++[------>+<]>+++++++++.--.--

$ sharps encode.ss -42
++[------>+<]>++.+++++++.--.--

$ sharps encode.ss 1.427
++[------>+<]>++++++.---.++++++.--.+++++.-------

$ sharps encode.ss -946.427
++[------>+<]>++.++++++++++++.-----.++.--------.++++++.--.+++++.-------

Запуск у Linux:

$ WINEDEBUG=-all wine sharps source.ss -4.72
++[------>+<]>++.+++++++.------.+++++++++.-----.--

Підтвердити в Інтернетному перекладачі BF .

Оцінки:

  1. Базова середня = 37.495.
  2. Десяткове середнє = 60.959 * 0.5 = ~30.48.
  3. Негативна середня. = 38.4765234765235 * 0.9 = ~34.629
  4. Середнє вище, підсумковий бал = (37.495 + 30.48 + 34.629)/3 = 34.201.

1
Мені завжди подобається бачити нові мови. :) Дякую за розбиття балів! Я хотів би поставити більше бонусу на десяткову частину, тому я змінив відрахування з 40% на 50%.
ETHproductions

@ETHproductions Так, я спробую створити для цього інтернет-перекладача. Існує близько 435 високо абстрактних операторів, додаткові 9,9k можна визначити ;-). Я виправив розрахунок (сподіваюся).
mınxomaτ

3

Рубі / Рубі, 29.77885

31,873 * 0,9 (негативно) 30,872 (позитивно).

Основна стратегія - це симетричне представлення основи 3 ("збалансоване трійкове"), тобто коли цифри -1,0,1замість них0,1,2

#function
f=->n{m=n  
  a='0' 
  7.times{|i|
    r=m%3;r-=r/2*3
    m=(m-r)/3
    #produce expression: replace 0 with (0*x+-1)
    #only add 0*x if there are higher base 3 digits to follow.
    #only add (..+-1) if the current base 3 digit is nonzero. 
    a.sub!('0',['','(','('][r]+(m.abs>0?'0*x':'')+['','+1)','-1)'][r])
  }
  #tidy up expression
  a.sub!('(-1)*','-')          #remove internal (-1)*
  a.sub!('(+1)*','')           #remove internal (+1)*
  a[-1]==')' && a=a[1..-2]     #remove unnecessary global brackets
  a.sub!('x','(x=1+1+1)')      #find the first x and define it as 1+1+1=3
  #special cases for small numbers 
  n.abs<8 && a=n==0?'0':['','1'+'+1'*(n-1).abs,'-1'*n.abs][n<=>0] 
  a 
}

#call like this
(1..1000).each{|p|
b=f.call(p)
puts b

Ось вихід від 0 до 40 перед очищенням

(+1)
((+1)*x-1)
(+1)*x
((+1)*x+1)
(((+1)*x-1)*x-1)
((+1)*x-1)*x
(((+1)*x-1)*x+1)
((+1)*x*x-1)
(+1)*x*x
((+1)*x*x+1)
(((+1)*x+1)*x-1)
((+1)*x+1)*x
(((+1)*x+1)*x+1)
((((+1)*x-1)*x-1)*x-1)
(((+1)*x-1)*x-1)*x
((((+1)*x-1)*x-1)*x+1)
(((+1)*x-1)*x*x-1)
((+1)*x-1)*x*x
(((+1)*x-1)*x*x+1)
((((+1)*x-1)*x+1)*x-1)
(((+1)*x-1)*x+1)*x
((((+1)*x-1)*x+1)*x+1)
(((+1)*x*x-1)*x-1)
((+1)*x*x-1)*x
(((+1)*x*x-1)*x+1)
((+1)*x*x*x-1)
(+1)*x*x*x
((+1)*x*x*x+1)
(((+1)*x*x+1)*x-1)
((+1)*x*x+1)*x
(((+1)*x*x+1)*x+1)
((((+1)*x+1)*x-1)*x-1)
(((+1)*x+1)*x-1)*x
((((+1)*x+1)*x-1)*x+1)
(((+1)*x+1)*x*x-1)
((+1)*x+1)*x*x
(((+1)*x+1)*x*x+1)
((((+1)*x+1)*x+1)*x-1)
(((+1)*x+1)*x+1)*x
((((+1)*x+1)*x+1)*x+1)

І після прибирання

0
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
(x=1+1+1)*x-1
(x=1+1+1)*x
(x=1+1+1)*x+1
((x=1+1+1)+1)*x-1
((x=1+1+1)+1)*x
((x=1+1+1)+1)*x+1
(((x=1+1+1)-1)*x-1)*x-1
(((x=1+1+1)-1)*x-1)*x
(((x=1+1+1)-1)*x-1)*x+1
((x=1+1+1)-1)*x*x-1
((x=1+1+1)-1)*x*x
((x=1+1+1)-1)*x*x+1
(((x=1+1+1)-1)*x+1)*x-1
(((x=1+1+1)-1)*x+1)*x
(((x=1+1+1)-1)*x+1)*x+1
((x=1+1+1)*x-1)*x-1
((x=1+1+1)*x-1)*x
((x=1+1+1)*x-1)*x+1
(x=1+1+1)*x*x-1
(x=1+1+1)*x*x
(x=1+1+1)*x*x+1
((x=1+1+1)*x+1)*x-1
((x=1+1+1)*x+1)*x
((x=1+1+1)*x+1)*x+1
(((x=1+1+1)+1)*x-1)*x-1
(((x=1+1+1)+1)*x-1)*x
(((x=1+1+1)+1)*x-1)*x+1
((x=1+1+1)+1)*x*x-1
((x=1+1+1)+1)*x*x
((x=1+1+1)+1)*x*x+1
(((x=1+1+1)+1)*x+1)*x-1
(((x=1+1+1)+1)*x+1)*x
(((x=1+1+1)+1)*x+1)*x+1

Я вважаю, що це називається "збалансованим трійником".
lirtosiast

@ThomasKwa відредаговано, спасибі
Level River St

3

Цейлон / Цейлон, 49,86 40,95 бала

У третій версії використовується Ceylon 1.2 для генератора та 509 байт коду:

import ceylon.language{S=String,I=Integer,e=expand}S q(I n)=>n==0then"0"else(n<0then"-"+p(-n,"-")else p(n,"+"));variable Map<[I,S],S>c=map{};S p(I n,S s){S v=c[[n,s]]else(n<8then s.join([1].repeat(n)))else(let(a="+-".replace(s,""))e(e{for(x in 2..8)let(l=(n^(1.0/x)).integer){for(r in l:2)if(r>1)let(w=r^x){if(w-n<n)"("+p(r,"+")+")^("+p(x,"+")+")"+(w<n then s+p(n-w,s)else(n<w then a+p(w-n,a)else""))}}}).reduce<S>((x,y)=>x.size<y.size then x else y))else"";c=[n,s]in c then c else map{[n,s]->v,*c};return v;}

Він знижується до 35,22 балів, але я не заношу це в заголовок, тому що Celyon 1.2 був опублікований лише 29 жовтня. Я не думаю, що я міг би реалізувати цей алгоритм на Цейлоні 1.1 у такому розмірі.) Більше деталей там, тут я опишу другу версію. (Першу версію можна побачити в історії - вона підтримувала лише додатні числа, але вкладалася в 256 байт.)

Друга версія

Тепер друга версія, яка підтримує негативні цілі числа (і 0), і, як правило, створює трохи коротший вихід, використовуючи додатково -. (Ця версія фактично використовує дозволену довжину. Перша намагалася залишатися під 256 байтами замість 512.)

String proof(Integer n) {
    if (n == 0) { return "0"; }
    if (n < 0) { return "-" + p(-n, "-"); }
    return p(n, "+");
}
String p(Integer n, String sign) {
    if (n < 9) {
        return sign.join([1].repeat(n));
    }
    value anti = (sign == "+") then "-" else "+";
    value root = ((n^0.5) + 0.5).integer;
    return "(" + p(root, "+") + ")^(1+1)" +
       ( (root^2 < n) then sign + p(n - root^2, sign) else
         ((n < root^2) then anti + p(root^2 - n, anti) else ""));
}

Код має довжину 487, тому пізніше залишається простір для більшої оптимізації. (Існує також багато резервів у вигляді пробілів і довгих змінних назв.)

Оцінка:

Total positive: 42652
Average positive:42.652
Total negative: 43653
Average negative: 43.60939060939061
With bonus:39.24845154845155
Overall score: 40.95022577422577

Деякі результати вибірки:

   27:  21: (1+1+1+1+1)^(1+1)+1+1
   28:  23: (1+1+1+1+1)^(1+1)+1+1+1
   29:  25: (1+1+1+1+1)^(1+1)+1+1+1+1
   30:  27: (1+1+1+1+1)^(1+1)+1+1+1+1+1
   31:  29: (1+1+1+1+1+1)^(1+1)-1-1-1-1-1
   32:  27: (1+1+1+1+1+1)^(1+1)-1-1-1-1
   33:  25: (1+1+1+1+1+1)^(1+1)-1-1-1
   34:  23: (1+1+1+1+1+1)^(1+1)-1-1

  -27:  22: -(1+1+1+1+1)^(1+1)-1-1
  -28:  24: -(1+1+1+1+1)^(1+1)-1-1-1
  -29:  26: -(1+1+1+1+1)^(1+1)-1-1-1-1
  -30:  28: -(1+1+1+1+1)^(1+1)-1-1-1-1-1
  -31:  30: -(1+1+1+1+1+1)^(1+1)+1+1+1+1+1
  -32:  28: -(1+1+1+1+1+1)^(1+1)+1+1+1+1
  -33:  26: -(1+1+1+1+1+1)^(1+1)+1+1+1
  -34:  24: -(1+1+1+1+1+1)^(1+1)+1+1


  993:  65: ((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
  994:  63: ((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
  995:  61: ((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
  996:  59: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1
  997:  57: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1
  998:  55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1
  999:  53: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)
 1000:  55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)+1

 -993:  66: -((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
 -994:  64: -((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
 -995:  62: -((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
 -996:  60: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1
 -997:  58: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1
 -998:  56: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1
 -999:  54: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)
-1000:  56: -((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:   3: 1+1
    3:   5: 1+1+1
    4:   7: 1+1+1+1
    5:   9: 1+1+1+1+1
    6:  11: 1+1+1+1+1+1
    7:  13: 1+1+1+1+1+1+1
    8:  15: 1+1+1+1+1+1+1+1
    9:  13: (1+1+1)^(1+1)
   10:  15: (1+1+1)^(1+1)+1

    0:   1: 0
   -1:   2: -1
   -2:   4: -1-1
   -3:   6: -1-1-1
   -4:   8: -1-1-1-1
   -5:  10: -1-1-1-1-1
   -6:  12: -1-1-1-1-1-1
   -7:  14: -1-1-1-1-1-1-1
   -8:  16: -1-1-1-1-1-1-1-1
   -9:  14: -(1+1+1)^(1+1)
  -10:  16: -(1+1+1)^(1+1)-1

Як бачите, негативні завжди на один байт (провідніші -) довші за відповідні позитивні.

Основна ідея така ж, як і в попередній програмі: знайдіть квадрат біля нашого цільового числа та представляйте його корінь та решту рекурсивно. Але тепер ми допускаємо, щоб наша площа була і деякою більшою, ніж цільове число, що потім робить решту негативною. ( +0.5Можна змінити на іншу константу, щоб налаштувати алгоритм, але, здається, я вже досяг оптимального тут - і 0,4, і 0,6 дають гірші результати.)

Щоб негативні значення були негативними (і в іншому випадку мали таку ж структуру, як і позитивні, ми передаємо оператору signнашу рекурсивну функцію p- тобто або "+"або "-". Ми можемо використовувати це для столяра і в тривіальних випадках (тобто n <9) що стосується залишків, якщо він позитивний, а для залишку використовуйте протилежний знак, якщо він негативний.

У proofфункції ручки початковий знак (з особливим випадком для 0), то pфункція виконує фактичну роботу, з допомогою рекурсії.

Третя версія, для Цейлона 1.2

import ceylon.language { S=String, I=Integer,e=expand }

// output a base-proof Ceylon expression for an integer
// (i.e. using only 0 and 1 as digits).
//
// Question: http://codegolf.stackexchange.com/q/58084/2338
// My Answer:  http://codegolf.stackexchange.com/a/58122/2338
//
// The goal is to produce an expression as short as possible, with
// the code staying under 512 bytes in length.
//
// This approach is to represent a positive integer as a square
// of a positive integer plus some remainder (where the remainder
// can be negative), and for negative integers replace the + on the
// outer level by -.

S q(I n) =>
        n == 0 then "0"
        else (n < 0 then "-" + p(-n, "-")
            else p(n, "+"));

// cache for values of p
variable Map<[I, S],S> c = map { };

// Transforms a positive number into a base-proof term, using
// the given sign for the summation on the outer level.
S p(I n, S s) {
    S v =
    // look into the cache
            c[[n, s]] else (
        // hard-code small numbers
        n < 8 then s.join([1].repeat(n)))
            else
    // do the complicated stuff
    (let (a = "+-".replace(s,""))
            e(e {
                    for (x in 2..8) // try these exponents
                        let (l = (n ^ (1.0 / x)).integer) // \[ sqrt[exp]{n} \] in LaTeX
                            { for (r in l:2) // lowerRoot, lowerRoot + 1
                                    if (r > 1)
                                        let (w = r ^ x)
                                            { if (w-n < n) // avoid recursion to larger or same number
                                                    // format the string as  r^x + (n-w)
                                                    "(" + p(r, "+") + ")^(" + p(x, "+") + ")" +
                                                            (w < n then s + p(n - w, s)
                                                                else (n < w then a + p(w - n, a)
                                                                    else ""))
                                            } } })
            // and now find the shortest formatted string
                .reduce<S>((x, y) => x.size < y.size then x else y))
    // this should never happen, but we can't tell the compiler
    // that at least some of the iterables are non-empty due to the if clause.
            else "";

    // this builds a new cache in each step – quite wasteful,
    // as this also happens when the value was found in the cache,
    // but we don't have more characters remaining.
    //// c = map { [n, s] -> v, *c };
    ///better way:
     c = [n,s] in c then c else map{[n,s]->v, *c}; 
    return v;
}

Версія для гольфу (тобто коментарі та пробіли вилучені) розміщується вгорі, рівно на 509 байтів коду.

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

Оцінка:

Total positive: 36622
Average positive: 36.622
Total negative: 37623
Average negative: 37.58541458541458
With bonus:33.826873126873124
Overall score: 35.22443656343656

Велика відрізна конструкція в середині - це три вкладені ітерабельні розуміння, внутрішні два усередині висловлювання. Потім вони знімаються за допомогою функції розширення двічі, і reduceфункція знаходить найкоротшу з цих рядків.

Я подав запит на функцію, щоб мати змогу це зробити за одне розуміння.

Всередині розуміння ми будуємо рядок із кореня r, експонента xта решти ( n-wабо w-n).

letВираз і mapфункції є новими в Цейлоні 1.2. mapміг бути замінений на HashMap(що знадобилося б більше символів для імпорту, хоча це, мабуть, було б ще швидше, оскільки я не будував би нову карту для кожного нового запису). Ці letвирази , як let (w = r ^ x)могли б бути замінені за допомогою ifзастереження , як if(exists w = true then r ^ x)(і тоді я не потребував би в двох expandвикликів або), але це все одно буде трохи більше, не вписується в 511 дозволених байтів.

Тут вибіркові виходи, що відповідають обраним вище, всі вони, крім дійсно невеликих чисел, коротші:

   27:  15: (1+1+1)^(1+1+1)
   28:  17: (1+1+1)^(1+1+1)+1
   29:  19: (1+1+1)^(1+1+1)+1+1
   30:  21: (1+1)^(1+1+1+1+1)-1-1
   31:  19: (1+1)^(1+1+1+1+1)-1
   32:  17: (1+1)^(1+1+1+1+1)
   33:  19: (1+1)^(1+1+1+1+1)+1
   34:  21: (1+1)^(1+1+1+1+1)+1+1

  -27:  16: -(1+1+1)^(1+1+1)
  -28:  18: -(1+1+1)^(1+1+1)-1
  -29:  20: -(1+1+1)^(1+1+1)-1-1
  -30:  22: -(1+1)^(1+1+1+1+1)+1+1
  -31:  20: -(1+1)^(1+1+1+1+1)+1
  -32:  18: -(1+1)^(1+1+1+1+1)
  -33:  20: -(1+1)^(1+1+1+1+1)-1
  -34:  22: -(1+1)^(1+1+1+1+1)-1-1

  993:  39: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1-1
  994:  37: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1
  995:  35: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1
  996:  33: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1
  997:  31: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1
  998:  29: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1
  999:  27: ((1+1+1)^(1+1)+1)^(1+1+1)-1
 1000:  25: ((1+1+1)^(1+1)+1)^(1+1+1)

 -993:  40: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1+1
 -994:  38: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1
 -995:  36: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1
 -996:  34: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1
 -997:  32: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1
 -998:  30: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1
 -999:  28: -((1+1+1)^(1+1)+1)^(1+1+1)+1
-1000:  26: -((1+1+1)^(1+1)+1)^(1+1+1)

    1:   1: 1
    2:   3: 1+1
    3:   5: 1+1+1
    4:   7: 1+1+1+1
    5:   9: 1+1+1+1+1
    6:  11: 1+1+1+1+1+1
    7:  13: 1+1+1+1+1+1+1
    8:  13: (1+1)^(1+1+1)
    9:  13: (1+1+1)^(1+1)
   10:  15: (1+1+1)^(1+1)+1

    0:   1: 0
   -1:   2: -1
   -2:   4: -1-1
   -3:   6: -1-1-1
   -4:   8: -1-1-1-1
   -5:  10: -1-1-1-1-1
   -6:  12: -1-1-1-1-1-1
   -7:  14: -1-1-1-1-1-1-1
   -8:  14: -(1+1)^(1+1+1)
   -9:  14: -(1+1+1)^(1+1)
  -10:  16: -(1+1+1)^(1+1)-1

Наприклад, тепер маємо 1000 = (3 ^ 2 + 1) ^ 3, замість 1000 = (6 ^ 2-4) ^ 2-5 ^ 2 + 1.


Я неправильно запам'ятав обмеження програми, як 256 байт ... в 512 можна зробити трохи більше. Спробую це пізніше.
Paŭlo Ebermann

Ні, це говорить less than 512. Ви можете використовувати макс. з 511 байт;)
mınxomaτ

Як я ніколи не чув цієї мови?!? : O Але серйозно, відмінне пояснення! Я люблю розуміти методи, які інші використовують у своїх відповідях. +1
ETHproductions

@ETHproductions я також читав про це близько двох тижнів тому тут, на сайті, і мені це подобалося. Отож, щоб краще познайомитися з цим, я намагаюся відповісти на питання тут, використовуючи Цейлон.
Paŭlo Ebermann

2

Ruby / DC, 20.296 18.414 16.968

Динамічне програмування! Визначає перелік функцій, які, даючи інструкцію dc, повертають новий вираз та числове значення цього виразу. Потім, починаючи з1 попередньо визначеного, він створює список усіх доступних значень до і включає шукане значення.

редагувати:

Додана функція для n-1 і змусила запустити алгоритм через кілька проходів. Здається, для стабілізації потрібно 7 проходів. Довелося скоротити деякі імена змінних, щоб залишатися в межах 512 байт.

редагувати 2:

Додано функції для n (n-1) , n (n + 1) і n ^ 3, поки я був на ній. Скоротивши код ще трохи, розмістивши рівно 512 байт.

N = gets.to_i

fns = [
  ->(n,s){[n-1,   s+'1-']},
  ->(n,s){[n+1,   s+'1+']},
  ->(n,s){[n*2,   s+'d+']},
  ->(n,s){[n*3,   s+'dd++']},
  ->(n,s){[n*~-n, s+'d1-*']},
  ->(n,s){[n*n,   s+'d*']},
  ->(n,s){[n*-~n, s+'d1+*']},
  ->(n,s){[n*n*n, s+'dd**']},
]

lst = []*(N+1)
lst[0..2] = %w[0 1 1d+]

loop do
  prev = lst.dup

  (1..N).each do |n|
    fns.each do |f|
      m,s = f[n, lst[n]]
      lst[m] = s if m <= N && (lst[m].nil? || lst[m].size > s.size)
    end
  end

  break if lst == prev
end

puts lst[N]

Згенеровані числа:

Вихід складається повністю з п'яти різних символів: 1висуває значення 1 на стек; dдублює верхню частину стека; +, -та * з'являє два найвищі значення та підштовхує їх суму, різницю та продукт відповідно. Кожен згенерований вираз додає лише одне значення до стеку після виконання.

   1: 1
   2: 1d+
   3: 1dd++
   4: 1d+d+
   5: 1d+d+1+
   6: 1d+dd++
   7: 1d+dd++1+
   8: 1d+dd**
   9: 1dd++d*
  10: 1d+d+1+d+
  11: 1d+d+1+d+1+
  12: 1dd++d1+*
  13: 1dd++d1+*1+
  14: 1d+dd++1+d+
  15: 1d+d+d*1-
  16: 1d+d+d*
  17: 1d+d+d*1+
  18: 1dd++d*d+
  19: 1dd++d*d+1+
  20: 1d+d+d1+*
  21: 1d+d+d1+*1+
  22: 1d+d+1+d+1+d+
  23: 1d+dd**dd++1-
  24: 1d+dd**dd++
  25: 1d+d+1+d*

...

 989: 1d+d+d*d+d1-*1-1-1-
 990: 1d+d+d*d+d1-*1-1-
 991: 1d+d+d*d+d1-*1-
 992: 1d+d+d*d+d1-*
 993: 1d+d+d*d+d1-*1+
 994: 1d+d+d*d+d1-*1+1+
 995: 1d+d+d*d+d1-*1+1+1+
 996: 1d+d+1+dd**d+1-d+d+
 997: 1d+d+1+d+dd**1-1-1-
 998: 1d+d+1+d+dd**1-1-
 999: 1d+d+1+d+dd**1-
1000: 1d+d+1+d+dd**

1
Досить добре, побивши все, крім z80 машинного коду досі (навіть Dennis 'CJam!). Як ви думаєте, ви могли б додати -оператора під час перебування в кількості байтів?
ETHproductions

@ETHproductions Як це? ;) Зараз також не повинно бути складно додавати від’ємні числа.
daniero

0

Пітон 2,6, 78,069 - 66,265 балів

Подання моєї відповіді на те, чого вона варта (не багато в цьому випадку ... але чітко продемонструвавши, що для цього виклику недостатньо просто думати про складання результату як суму зсувних значень; якщо врахувати, що немає цифр за межами 0 або 1 може з’явитися у виході). Я можу повернутися пізніше з іншим способом отримання продукції.

Сам код не надто довгий (176 символів):

def f(a):return'+'.join(('(1<<%s)'%['0','+'.join('1'*x)][x>0]).replace('(1<<0)','1')for x in[i for i,e in enumerate(bin(a)[::-1][:-2])if int(e)])
print"".join(f(int(input())))

Він генерує правильний, але багатослівний вихід:

17
1+(1<<1+1+1+1)

800
(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)

Фрагмент, який обчислює бал:

def f(a):return'+'.join(('(1<<%s)'%['0','+'.join('1'*x)][x>0]).replace('(1<<0)','1')for x in[i for i,e in enumerate(bin(a)[::-1][:-2])if int(e)])
print sum(len("".join(f(i)))for i in range(1000))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.