{Кучеряві номери};


33

На мові езотеричного програмування Curly, програми складаються виключно з фігурних дужок {}і крапки з комою ;. Незважаючи на цей скромний набір інструментів, у Curly є літерали, які можуть представляти будь-яке невід’ємне ціле число. Формат трохи важко читати незнайомим, тому давайте напишемо якийсь код, щоб зробити перетворення для нас.

Формат чисел

Фігурні цифри структуровані за такими правилами:

  1. Додавання крапки з комою додає один до числа.
  2. Число, вкладене в фігурні дужки, множиться на чотири.
  3. Кучеряво-фігурні групи можуть бути вкладені, але не зв'язані. Підтяжки повинні відповідати належним чином.
  4. Крапки з комою поза набором фігурних дужок повинні надходити згодом, а не раніше.
  5. Щоб уникнути неоднозначності при розборі, число завжди повинно починатися з фігурної дужки.

Деякі приклади:

{;;}     2*4 = 8
{{;};};  (1*4+1)*4+1 = 21
{};;;    0*4+3 = 3

(Зверніть увагу, що правило 5 означає, що цифри від 0 до 3 повинні починатися з порожньої пари фігурних дужок.)

І кілька недійсних прикладів:

{{;}{;;}}  Curly brace groups side-by-side, not nested
{;}}       Unmatched brace
{;{;}}     Semicolon before curly-brace group
;;;        Number does not start with curly brace

Ось граматика BNF для фігурних чисел:

<number> ::= "{" <inner> "}" <semis>
<inner>  ::= <semis>
           | <number>
<semis>  ::= ";" <semis>
           | ""

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

Змагання

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

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

Вихід може бути надрукований в STDOUT або повернутий з функції. Функція може повернути ціле число, коли це доречно, або може повернути рядки у будь-яких ситуаціях.

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

Оцінка балів

Виграє найкоротший код у байтах. Якщо ваша програма може зробити як в наступному:

  1. правильно обробляти неправильні фігурні номери та
  2. коли вам надано фігурне число, ігноруйте зайві символи, яких немає {};

потім відніміть 10% від вашої оцінки. (Введення цілого числа ніколи не матиме сторонніх символів, навіть бонус.)

Тестові справи

Input       Output
{;;}        8
{{;};};     21
{};;;       3
{{{{;}}};}  260
{}          0
4           {;}
17          {{;}};
1           {};
0           {}
96          {{{;};;}}

Для бонусу:

{};;;;;     5
{{;;;;};;}  72
c{u;r;l}y;! 9
42{;} ;;;;  8

Примітка: Curly ще не реалізовано. Але якщо це питання добре, я можу розвинути його далі.


як слід поводитися з регістром, якщо у вас немає відповідних кількості дужок? чи я припускаю, що це ніколи не відбудеться?
user902383

@ user902383 Ви можете припустити, що невідповідні фігурні дужки ніколи не відбудуться.
DLosc

2
Я збирався зробити рішення Retina, але, змусивши його обробити рядок Curly (всього 20 байт), я зрозумів, що він також повинен обробляти додатні цілі числа -> Curly, тому я відмовився.
mbomb007

@DLosc Так, це не виграє, тому я не збираюся витрачати час.
mbomb007

@ mbomb007 Я мав на увазі саме це питання, де рішення Pyth вже на 22% коротше, ніж найкоротший CJam-рішення і кваліфікується на бонус. У всякому разі, це було риторичне запитання, яке намагалося сказати: "Ні, але це все одно може бути весело і зібрати деякі результати". Якщо ви не згодні з "веселою" частиною, це все добре.
DLosc

Відповіді:


15

Pyth, 35 32 байти - 10% = 28,8

.x.U+jb`HZ*R\;.[Z2jsz4i/R\;cz\}4

Спробуйте в Інтернеті: Демонстрація або Тестовий набір

редагувати: Як виявилося, я випадково також можу впоратись із неправильними фігурними цифрами. Це взагалі не планувалося. ;-)

Пояснення:

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

.U+jb`HZ*R\;.[Z2jsz4   # number to Curly Number
                 sz    read the input and converts it to an int
                j  4   convert to base 4
            .[Z2       pad zeros on the left, until length is >= 2
        *R\;           convert each digit to ";"s
                       lets call this list of ";"s Y
.U                     reduce this list, start with b=Y[0], 
                       Z iterates over Y[1], Y[2], ..., 
                       update b in each step with:
   jb`H                   put b into curly brackets
  +    Z                  and append Z

i/R\;cz\}4             # Curly Number to regular number
     cz\}              split the input by "}"
 /R\;                  count the ";"s in each string
i        4             convert this list from base 4 to base 10

2
Найшвидший пістолет на заході :( у мене було таке точне рішення, за винятком того, що я забув, що це .[Z2необхідно.
orlp

12

CJam, 51 47 44 41 байт

r_'{-_@={i4bYUe[';f*{{}s@*\+}*}{'}/:,4b}?

Спробуйте в Інтернеті: зразок запуску | тестовий набір

Як це працює

r        e# Read a token from STDIN.
_'{-     e# Remove all left curly brackets from a copy of the token.
_@       e# Copy the modified token and rotate the original on top of it.
=        e# Check for equality.
{        e# If the strings were equal:
  i4b    e#   Convert to integer, then to base 4.
  YUe[   e#   Left-pad the resulting array with zeroes to a length of 2.
  ';f*   e#   Replace each digit with that many semicolons.
  {      e#   For each string of semicolons but the first:
    {}s  e#     Push the string "{}".
    @    e#     Rotate the first string or the result of the previous 
         e#     iteration on top of the stack.
    *    e#     Join, i.e., surround the string with curly brackets.
    \+   e#     Append the current string of semicolons to the result.
  }*     e#
}{       e# Else:
  '}/    e#   Split the modified input at right curly brackets.
  :,     e#   Replace each run of 0 to 3 semicolons by its length.
  4b     e#   Convert from base 4 to integer.
}?       e#

7

Python 2, 167 байт - 10% = 150,3

d=lambda x:("{"+d(x//4)+"}"if x>3 else"")+";"*(x%4)
c=lambda n:"{}"*(int(n)<4)+d(int(n))if n.isdigit()else reduce(lambda x,y:x*4+y,[x.count(";")for x in n.split("}")])

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


6

Python 266 байт - 10% = 1268,1 326,7 239,4 байт

Хлопчик, я ще не гольфіст з кодом = /, але це 10% мені дуже допомогло , коли мій показник був понад 1000!

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

(Коментарі лише для уточнення)

Дивіться цей код у дії

def c(t):                           # curly to int function
 v=0                                #  int value of input
 for a in t:                        #  for each character of input
  if a==';':v+=1                    #   if you find a ';', add one to total
  if a=='}':v*=4                    #   if you find a '}', multiply total by 4
 print v                            #  print value
def i(t):                           # int to curly function
 v=int(t);f,b="{}"if v<4 else"",""  #  get integer value. initialize front (f) and back (b) strings
 while 1:                           #  loop until stopped
  r,v=v%4,int(v/4)                  #   get remainder of v/4 and int value of v/4
  if r>0:b=';'*r+b                  #   if remainder exists, prepend that many ';' to back string
  if v>0:f=f+'{';b='}'+b            #   if remaining value > 4, append '{' to front and prepend '}' to back
  if v<4:b=';'*v+b;break            #   if remaining value < 4, prepend that many ';' to back string and break
 print f+b                          #  print result
t=raw_input()                       # get raw input
try:int(t);i(t)                     # use try block to determine which function to call
except:c(t)                         # 

Дякуємо Еріку Констапопулосу за основне скорочення байтів! Можна сказати ... він насправді взяв ... байт ... з мого коду ... * я п'ять *


4
Ласкаво просимо до PPCG! Ваш код містить багато непотрібних printвисловлювань та коментарів, ваші імена змінних занадто довгі, а деякі пробіли можна усунути. Я також рекомендую прочитати Поради щодо гольфу в Pyrhon .
Денніс

Чудовий ресурс, спасибі! Я внесу відповідні зміни до цього коду і побачу, наскільки він мені дістається. Схоже, якщо я хочу бути ким-небудь на цьому веб-сайті, мені потрібно або вивчити CJam або Pyth, або написати свою власну мову lol.
Тейлор Лопес

3
@iAmMortos Не обов'язково . Робіть, якщо вам це подобається, або дотримуйтесь Python, якщо ні. :)
DLosc

2
Зазвичай гольф проводиться в три етапи: 1) зробіть свою програму так, як ви б робили нормально, як мінімум (тобто відсутні заяви про налагодження, не потрібно обробляти неправильний ввід, мінімальний вихід) 2) видаліть якомога більше : пробіли , перейменуйте змінні ( valueі vт. д.), 3) робіть розумні речі з гольфу : саме тут вам потрібно поглянути на посилання Денніса. Мені цікаво побачити, скільки ви можете скоротити це!
Санчіз

1
Ніколи в громаді я не отримував такого теплого прийому. хаха, я думаю, що мені тут подобається.
Тейлор Лопес

4

CJam, 87 байт 80,1 бал (89 байт - 10% бонус)

Оновіть версію, яка має право на бонус, зростаючи на 2 байти:

l_'{#){VX@{";{}"#)" _@+\ 4* 4/"S/=~}/;}{i_4<{"{}"\';*}{{4md\_{F'{\+'}+}{;L}?\';*+}:F~}?}?

Спробуйте в Інтернеті

Перший раз я використав рекурсію в CJam! Вся справа може виглядати тривало, але ці дві окремі конверсії складаються.

Я використовував абсолютно окремий випадок для перетворення чисел, менших ніж 4, у Curly. Цього можливо, можливо, уникнути, але складання режиму обробки спеціального корпусу в рекурсивну функцію не було б цілком тривіальним. І додавання додаткового {}кроку як крок після обробки насправді не виглядало кращим, хоча я повинен спробувати ще раз, якщо він може бути трохи коротшим.


Не став би ваш бал 80,1?
PurkkaKoodari

4
@ Pietu1998 Дякую Мало того, що мої рішення занадто довгі, мабуть, я також провалююсь в базовій арифметиці ...
Рето Коради

3

C #, 173 - 10% = 155,7 171,0, 177,3

Це не робить ніякої перевірки і тільки шукає ;і }символів. Передбачається, що всі {символи стають перед будь-якими ;символами. Найважче, що я знайшов, - це не вставляти {}в середині фігурного числа.

Розриви рядків та відступи для наочності:

string C(string a,int b=0){
    int n;
    if(int.TryParse(a,out n))
        a=(n>=b?"{"+C(""+n/4,4)+"}":"")+";;;".Remove(n%4);
    else
        foreach(int c in a)
            a=""+(c==59?++n:c==125?n*=4:n);
    return a;
}

Ви можете зберегти один байт, використовуючи var замість char у петлях foreach.
raznagul

@DLosc, вибачте, мене заплутав бонус №1. Я, хоча це стосується виводу, а не вводу.
Hand-E-Food

2

Java 326 байт - 10% = 294 байти

Це повна програма, написана на Java,

public class a{static String c(long a,int v){if(a==0)return v==0?"{}":"";String x="";for(int i=0;i<a%4;i++)x+=";";return "{"+c(a/4,v+1)+"}"+x;}public static void main(String[]c){try{System.out.println(c(Long.parseLong(c[0]),0));}catch(Exception e){System.out.println(c[0].chars().reduce(0,(a,b)->b==';'?a+1:b=='}'?a*4:a));}}}

Я впевнений, що це може бути набагато коротше, але я не можу зараз багато часу оптимізувати


@DLosc чорт, правда, і подумав, що я можу мати хороший результат з java :(
user902383

також: загальною оптимізацією на Java є уникання public попереднього класу
masterX244

замінити public static void main(String[]c){зstatic{
das_j

2

GNU sed, 330 326 - 10% = 293,4

(Я додав один для використання -rдо отримання бонусу 10%; я сподіваюся, що це правильно)

/;/{
s/[^};]//g
:c
s/(;*)\}/\1\1\1\1/
tc
:d
/;/{
s/;;;;;/v/g
s/vv/x/g
/[;v]/!s/\b/0/2
s/;;/b/g
s/bb/4/
s/b;/3/
s/v;/6/
s/vb/7/
s/v3/8/
s/v4/9/
y/;bvx/125;/
td
}
n
}
:u
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;]/s/;/&&&&&&&&&&/g
tu
:v
s/;;;;/v/g
s/v+/{&}/
y/v/;/
tv

Повна версія показує, що більша частина перерахованого вище - це перетворення між десятковою та одинаковою:

#!/bin/sed -rf

/;/{

# Delete non-Curly characters
s/[^};]//g

# Curly to unary
:c
s/(;*)\}/\1\1\1\1/
tc

# unary to decimal
:d
/;/{
s/;;;;;/v/g
s/vv/x/g
/[;v]/!s/\b/0/2
s/;;/b/g
s/bb/4/
s/b;/3/
s/v;/6/
s/vb/7/
s/v3/8/
s/v4/9/
y/;bvx/125;/
td
}

# done
n

}


# Decimal to unary
:u
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;]/s/;/&&&&&&&&&&/g
tu

# Unary to Curly
:v
s/;;;;/v/g
s/v+/{&}/
y/v/;/
tv

На жаль, в цьому питанні прямо написано, що десяткові потрібні, тому я переймався перетворенням.
Toby Speight

Ви маєте рацію, що мене трохи дивує, оскільки виключення унарного не було моїм наміром. Ну добре, здогадуйтесь, що зараз занадто пізно змінити питання. Я ще раз підтверджую свій +1, сер.
DLosc

2

Перл, 183 177

Це може бути не найкоротший відповідь Perl, але я думаю, що це досить цікаво для публікації (введення $_, вихід як повернене значення):

sub f{if(/}/){s/[{}]/00/g;oct'0b'.s/00(;+)/sprintf'%02b',length$1/ger}else{$_=sprintf'%064b',$_;s/../oct"0b$&"/ge;s/^0+(?!$)//;$_='{'x length.$_;s/\d/'}'.';'x$&/ge;s/\Q{{}/{/r}}

Ми спостерігаємо, що Curly - це просто четвертинна (база-4) позначення. Нас трохи заважає відсутність перлової підтримки четвертинки Perl, але, на щастя, кожен кватерніт є двома бітами в двійковій формі, і ми можемо читати і записувати бінарне. Отже, у нас є наступне:

  1. Кучеряве в десятковий: перетворіть кожну фігурну цифру у 2 двійкові цифри, з'єднайте та перетворіть у десяткові
  2. Десяткове значення для фігурного: надрукуйте число у двійковій формі (примушуючи парне число цифр), а потім перетворіть кожну біт-пару в фігурну.

Розширена версія

sub f
{
    if (/}/) {
        s/[{}]/00/g;     # digits are now 00 00; 00;; 00;;;
                         # and opening braces become harmless leading zeros
        s/00(;+)/sprintf'%02b',length $1/ge;
                         # convert semicolons to binary, leaving zeros alone
        oct "0b$_"       # now to decimal
    } else {
        $_=sprintf'%064b',$_;   # decimal to binary
        s/../oct"0b$&"/ge;      # bit-pair to quaternit
        s/^0+(?!$)//;           #/remove leading zeros
        $_='{'x length.$_;      # prefix enough opening braces
        s/\d/'}'.';'x$&/ge;     #/digit to semicolons
        s/{{}/{/r               # first empty brace, unless $_ <= {};;;
    }
}

1

JavaScript (ES6), 95 (105-10%)

f=(n,r='{}')=>-1-n?(n>3?'{'+f(n>>2,'')+'}':r)+';'.repeat(n&3):n.replace(/[;}]/g,c=>c>';'?n*=4:++n,n=0)&&n

Випробуйте запуск фрагмента нижче

f=(n,r='{}')=>-1-n?(n>3?'{'+f(n>>2,'')+'}':r)+';'.repeat(n&3)
:n.replace(/[;}]/g,c=>c>';'?n*=4:++n,n=0)&&n

// Test
function out(x) { O.innerHTML=x+'\n'+O.innerHTML; }

function go() { out(I.value + ' --> ' + f(I.value)) }

;[ 
  ['{;;}', 8]
, ['{{;};};', 21 ]
, ['{};;;', 3 ]
, ['{{{{;}}};}', 260 ]
, ['{}', 0 ]
, [ 4, '{;}' ]
, [ 17, '{{;}};' ]
, [ 1,'{};' ]
, [ 0, '{}' ]
, [ 96, '{{{;};;}}' ]
, ['{};;;;;', 5 ]
, ['{{;;;;};;}' , 72 ]
, ['c{u;r;l}y;!', 9 ]
, ['42{;} ;;;;', 8 ]
].forEach(t => {
  r=f(t[0])
  k=t[1]
  out('Test ' +(r==k?'OK':'Fail')+'\nInput:  '+t[0]+'\nResult: '+r+'\nCheck:  '+k+'\n')
})
Custom test <input id=I><button onclick='go()'>-></button>
<pre id=O></pre>


Чи можете ви опублікувати свій фактичний код? Також ваш бал - 94,5.
Ерік Аутгольфер

@ErikKonstantopoulos мій фактичний код був розміщений вгорі тестового фрагмента. Тепер воно також є у верхній частині відповіді. Щодо балу (який повинен бути в байтах), я завжди смішно вимірюю половину (або менше) байтів і віддаю перевагу рунінгу
edc65

edc65: Так, але округлення для вас погано! 94,5 <95, таким чином, менший бал, це означає, що він, ймовірно, перемагає більше подань. Крім того, "вершина фрагмента" не є місцем показу вашого коду.
Ерік Аутгольфер

1

Рубін, 126,9 129,6 (144 - 10%)

Використовує рекурсію для перетворення десятків у фігурну форму. Якщо зняти чек на ігнорування символів поза межами, кількість /[;{}]/балів 0.4наразі збільшується .

f=->s{s=~/^\d+$/?(n=s.to_i
"{#{n<1?'':f[(n/4).to_s].gsub('{}','')}}#{?;*(n%4)}"):eval(s.tr("^{;}","").gsub(/./){|c|c<?A?"+1":c>?|?")*4":"+(0"})}

Це зараз виправлено. Дякуємо за повідомлення про помилку; оцінка була оновлена.
Значення чорнила

1

Perl 5, 154 ( 185 170 байт - 10% + 1 штраф)

$e=$/;if($_=~/{/){s/[^{};]//g;s/;/+1/g;s/{/+4*(/g;s/}/+0)/g;$b=eval}else{$r=$_;$b=$r<4?"{}":"";while($r>0){if($r%4>0){$r--;$e=";$e"}else{$b.="{";$e="}$e";$r/=4}}}$_=$b.$e

Regex & eval вирішують кучері.
Генерація кучериків робиться по-різному.

Тест

Тестовий файл містить також бонусні випадки

$ cat curlytestcases.txt
{}
{};
{};;
{};;;
{;;}
{{;};};
{{{{;}}};}
0
1
2
3
4
17
96
{};;;;;
42{;} ;;;;
c{u;r;l}y;!
{{;;;;};;}

$ cat curlytestcases.txt |perl -p curlies.pl
0
1
2
3
8
21
260
{}
{};
{};;
{};;;
{;}
{{;}};
{{{;};;}}
5
8
9
72

Додано -1 штраф за -p. $ B = $ r <2? "{}": ""; додано за винятком 0 & 1. {} ;;; - це вхід у тест.
LukStorms

Потрібно було трохи часу, щоб перевірити це. Це зараз виправлено. :)
LukStorms

Я думаю, що штраф +1 приходить після -10% бонусу.
Ерік Аутгольфер

Цікаве спостереження. Не впевнений, чи це зараз має бути, але це має сенс, тому я все-таки змінив його. Не те, щоб це змінило кінцевий бал.
LukStorms

1

Сітківка , 69 64 байт

+`{(;*)}
$1$1$1$1
^\d+|^(;*)
$*;$.1
+`(;+)\1\1\1
{$1}
^;|^$
{}$&

Спробуйте Suite


Пояснення

+`{(;*)}
$1$1$1$1

Розкладіть найпотаємніші брекети на просто ;s. Петля, поки немає більше дужок.

^\d+|^(;*)
$*;$.1

Перетворити між десятковим і одинаковим ;

+`(;+)\1\1\1
{$1}

Знайдіть найдовший пробіг, ;який є кратним 4, і вкладіть в дужки, петлюйте до тих пір, поки не існує більше циклів із 4+.

^;|^$
{}$&

Якщо отримане фігурне число починається з ;або є порожнім рядком, додайте {}спереду.


1

Python 2 , 157 байт -10% = 141,3

lambda n:'{}'*(int(n)<4)+g(int(n))if n.isdigit()else sum((v==';')*4**n.count('}',i)for i,v in enumerate(n))
g=lambda n:'{%s}'%g(n/4)+';'*(n%4)if n>3else';'*n

Спробуйте в Інтернеті!

Більш гольф відповіді Python 2, який обробляє бонусні випадки. Не хотіли оприлюднювати мертві пости з цим як коментарем, так ось це.

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


Це незручно. У мене навіть були тестові випадки для номерів менше 2. Виправлено на +5 байт.
Арнольд Палмер

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