Граф как вавилонянин


41

Вызов

Учитывая ASCII представление вавилонского числа в качестве входных данных, выведите число западно-арабскими цифрами.

Вавилонская система счисления

Как рассчитывали вавилоняне? Интересно, что они использовали систему Base 60 с элементом системы Base 10. Давайте сначала рассмотрим единичный столбец системы:

Вавилоняне имели только три символа: T(или, если вы можете сделать это :), 𒐕которые представляли 1, и <(или, если вы можете сделать это:), 𒌋которые представляли 10, и \(или, если вы делаете это:), 𒑊которые представляли ноль.

Примечание: Технически, \(или 𒑊) не ноль (потому что вавилоняне не имели понятия «ноль»). «Ноль» был изобретен позже, поэтому позже \был добавлен символ-заполнитель, чтобы предотвратить двусмысленность. Однако для целей этой задачи достаточно считать \ноль

Итак, в каждом столбце вы просто складываете значение символов, например:

<<< = 30
<<<<TTTTTT = 46
TTTTTTTTT = 9
\ = 0

В каждом столбце никогда не будет больше пяти <или больше девяти T. \всегда будет отображаться один в столбце.

Теперь нам нужно расширить это, добавив больше столбцов. Это работает точно так же, как и любое другое базовое значение шестьдесят, где вы умножаете значение самого правого столбца на , слева на , слева на и так далее. Затем вы складываете значение каждого, чтобы получить значение числа.600601602

Столбцы будут разделены пробелами, чтобы предотвратить двусмысленность.

Некоторые примеры:

<< <TT = 20*60 + 12*1 = 1212
<<<TT \ TTTT = 32*60^2 + 0*60 + 4*1 = 115204

правила

  • Вы можете принять ввод ASCII ( T<\) или Unicode ( 𒐕𒌋𒑊)
  • Введенное число всегда будет меньше107
  • <S всегда будет слева от Tй в каждой колонке
  • \ всегда будет появляться один в столбце

выигрыш

Самый короткий код в байтах побеждает.


2
@TaylorScott Да, вы можете
бета-распад

2
В случае, если это поможет: Макс, который должен быть обработан, составляет 4 столбца:<<<<TTTTTT <TTTTTTT <<<<TTTTTT <<<<
Wernisch

1
Всегда ли столбцы разделены ровно одним пробелом ? Я замечаю ответы, полагаясь на это.
KRyan

4
Иностранные типы с трубами для кальяна говорят: «О, о, о, о, о, о, о, о, о - считайте как вавилонянин» Отлично. Теперь он застрял в моей голове.
cobaltduck

5
"How did the Babylonians count? Interestingly, they used a Base 60 system with an element of a Base 10 system."Который все еще используется сегодня; Вавилонская система счисления - это именно то, что мы используем для часов. Две десятичные цифры каждая для секунд, минут и часов, 60 секунд до минуты, 60 минут до часа.
Рэй

Ответы:


39

JavaScript (ES6), 44 байта

Принимает ввод как массив символов ASCII.

a=>a.map(c=>k+=c<1?k*59:c<'?'?10:c<{},k=0)|k

Попробуйте онлайн!

Как?

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

Начиная с , каждый символ c во входном массиве a изменяет аккумулятор k следующим образом:k=0cak

  • space: умножить на 60 (реализовано как: добавить 59 k к k )k6059kk
  • <: добавь к k10k
  • T: приращение k
  • \: ничего не делать; это NOPинструкция этого языка (реализовано как: добавить к k )0k


11

Perl 6 , 39 байт

-3 байта благодаря nwellnhof

{:60[.words>>.&{sum .ords X%151 X%27}]}

Попробуйте онлайн!

Использует клинописные символы.

Объяснение:

{                                     }   # Anonymous code block
     .words  # Split input on spaces
           >>.&{                    }  # Convert each value to
                sum   # The sum of:
                    .ords # The codepoints
                          X%151 X%27   # Converted to 0,1 and 10 through modulo
 :60[                                ]  # Convert the list of values to base 60

Ты избил меня на пару минут. Вот то, что я придумал: {:60[.words>>.&{sum (.ords X%151)X%27}]}(40 байт)
nwellnhof

@nwellnhof Очень хорошо сделано! Как вы нашли значения модов?
Джо Кинг

2
Просто грубой силой.
nwellnhof

11

Желе ,  13  12 байт

ḲO%7C%13§ḅ60

Монадическая ссылка, принимающая список символов, который дает целое число.

Попробуйте онлайн!

Как?

ḲO%7C%13§ḅ60 - Link: list of characters   e.g. "<<<TT \ TTTT"
Ḳ            - split at spaces                 ["<<<TT", "\", "TTTT"]
 O           - cast to ordinals                [[60,60,60,84,84],[92],[84,84,84,84]]
  %7         - modulo by seven (vectorises)    [[4,4,4,0,0],[1],[0,0,0,0]]
    C        - compliment (1-X)                [[-3,-3,-3,1,1],[0],[1,1,1,1]]
     %13     - modulo by thirteen              [[10,10,10,1,1],[0],[1,1,1,1]]
        §    - sum each                        [32,0,4]
         ḅ60 - convert from base sixty         115204

Еще 12: ḲO⁽¡€%:5§ḅ60( ⁽¡€это 1013, так что это модули 1013со стороны Ordinal значений получает 53, 5и 1для <, T, \соответственно , а затем выполн ют целочисленное деление, с :помощью , 5чтобы получить 10, 1и 0)


Lol, я удалил свой ответ именно из-за этого, так как я помнил, что мог использовать базовое преобразование, но был буквально слишком ленив, чтобы узнать как. +1
г-н Xcoder

6

05AB1E , 13 байтов

8740|Ç%4/O60β

Попробуйте онлайн!

Чтобы восполнить, насколько ленивым я был с моим ответом Jelly, вот представление в 05AB1E xD.


Помогите 05AB1E-ers, не было ли способа сжать числа как 8740?
г-н Xcoder

2
codegolf.stackexchange.com/a/166851/52210 К сожалению, оно не будет короче: •Yη•(4 байта)
Кевин Круйссен,

2
@KevinCruijssen Спасибо! Этот ответ очень полезен, я буду полностью использовать его в будущем
г-н Xcoder

1
Рад, что совет полезен. :) Я понял это, увидев некоторые ответы, используя их. Часть словаря была объяснена здесь . А сжатие других строк или больших целых чисел я выяснил сам, увидев связанный пример ответов «гусь» и 246060 .
Кевин Круйссен

1|Ç7%-13%O60βтакже 13 - это гольф?
Джонатан Аллан

6

Python 2 , 96 93 87 85 байт

lambda s:sum(60**i*sum(8740%ord(c)/4for c in v)for i,v in enumerate(s.split()[::-1]))

Попробуйте онлайн!


Добавлено:

  • -1 байт, спасибо мистеру Xcoder
  • -4 байта, спасибо Пун Леви
  • -2 байта, спасибо Мэтью Дженсену

1
95:(ord(c)%5/2or 11)-1
г-н Xcoder

@ Mr.Xcoder Спасибо :)
TFeld

2
87:8740%ord(c)/4
Пун Леви

-2, удалив скобки вокруг второй суммы () Попробуйте онлайн!
Мэтью Дженсен

@MatthewJensen Спасибо :)
TFeld

4

Excel VBA, 121 байт

Ограничено 32-битным Office, так как ^служит LongLongлитералом типа в 64-битных версиях

Принимает данные из ячейки A1и выводит их в непосредственное окно vbe.

a=Split([A1]):u=UBound(a):For i=0 To u:v=a(i):j=InStrRev(v,"<"):s=s+(j*10-(InStr(1,v,"T")>0)*(Len(v)-j))*60^(u-i):Next:?s

Ungolfed и комментируется

a=Split([A1])       '' Split input into array
u=UBound(a)         '' Get length of array
For i=0 To u        '' Iter from 0 to length
v=a(i)              '' Get i'th column of input
j=InStrRev(v,"<")   '' Get count of <'s in input
                    '' Multiply count of <'s by 10; check for any T's, if present
                    ''   add count of T's
t=t+(j*10-(InStr(1,v,"T")>0)*(Len(v)-j))
    *60^(u-i)       '' Multiply by base
Next                '' Loop
?s                  '' Output to the VBE immediate window

4

Дьялог АПЛ , 33 30 байт

{+/(⌊10*⍵-360*+\2=⍵}'\ T<'⍳⌽

Попробуйте онлайн!

Редактировать: -3 байта благодаря ngn

'\ T<'⍳заменяет символы числами (их положение в строковой константе) и переворачивает ввод, чтобы наиболее значимые «цифры» были последними. Это позволяет +\2=вести текущий подсчет желаемой степени 60 (применено 60*) путем подсчета количества встречений с пробелом (индекс 2 в строковой константе).

⌊10*⍵-3дает желаемую силу десяти для каждого персонажа. Порядок символов в строковой константе и смещение -3 приводят к тому, что '\' и пробел переходят в отрицательные числа, что приводит к дробным значениям, когда эти символы возводятся в степень 10, что позволяет их исключить с помощью .

Все, что нам нужно сейчас сделать, - это умножить числа степеней 10 на значения мест степеней 60 и суммировать с этим все +/.


сохранить несколько байтов, избегая отдельного сравнения с ' ':{+/(⌊10*⍵-3)×60*+\2=⍵}'\ T<'⍳⌽
ngn



3

APL (NARS ⎕io ← 0), 28 символов, 56 байтов

{60⊥{+/⍵⍳⍨10⍴'\T'}¨⍵⊂⍨⍵≠' '}

некоторый тест с проверкой типа:

  q←{60⊥{+/⍵⍳⍨10⍴'\T'}¨⍵⊂⍨⍵≠' '}

  o←⎕fmt
  o q '<< <TT'
1212
~~~~
  o q '<<<TT \ TTTT'
115204
~~~~~~

Каждый тип результата является числом.


2

JavaScript (Node.js) , 122 114 107 106 83 байта

a=>a.split` `.map(b=>[...b].map(c=>x+=c<'T'?10:c<'U',x=0)&&x).reduce((a,b)=>a*60+b)

Попробуйте онлайн!

Я немного одержим операциями с массивами в «функциональном стиле», использую ввод ASCII, насколько я могу судить, JS не очень хорош в получении кодов в гольфе

Я сохраняю это для потомков, но это наивное / глупое решение, я предлагаю вам проверить ответ Арно, который гораздо интереснее в реализации задачи


@ Шагги, похоже, работает на меня!
Скидсдев

c<'T'работает вместоc=='<'
г-н Xcoder

Сохраните еще 1, заменив &&на |.
Лохматый

@ Шагай и сэкономь намного больше, используя for...ofциклы: P
только ASCII

2

Сетчатка , 29 26 23 байта

<
10*T
+`^(.*)¶
60*$1
T

Попробуйте онлайн! Использует разделение новой строки, но ссылка включает заголовок, чтобы использовать пробелы вместо этого для удобства. Редактировать: 3 байта сохранены с помощью @KevinCruijssen. Сохранено еще 3 байта благодаря @FryAmTheEggman. Объяснение:

<
10*T

Замените каждый <с 10 Tс.

+`^(.*)¶
60*$1

Возьмите первую строку, умножьте ее на 60 и добавьте следующую строку. Затем повторяйте, пока не останется только одна строка.

T

Посчитай Tс.

Более быстрая 51-байтовая версия:

%`^(<*)(T*).*
$.(10*$1$2
+`^(.+)¶(.+)
$.($1*60*_$2*

Попробуйте онлайн! Использует разделение новой строки, но ссылка содержит заголовок, чтобы вместо этого использовать пробелы Объяснение:

%`^(<*)(T*).*
$.(10*$1$2

Подберите каждую строку отдельно и посчитайте количество Ts и в 10 раз больше числа <s. Это преобразует каждую строку в ее базовое 60-значное значение.

+`^(.+)¶(.+)
$.($1*60*_$2*

Преобразование базы 60, запуск линии за раз. Вычисление выполняется в десятичном формате для скорости.


Я уверен, что третья строка может быть просто <без +, если только я не вижу какой-то крайний случай.
Кевин Круйссен

1
@KevinCruijssen Еще лучше, так как $&теперь всегда один символ, я могу использовать символ по умолчанию, сохраняя еще два байта!
Нил

Ах, хорошо! :) Не знал, что можно сделать неявно для отдельных персонажей.
Кевин Круйссен

@KevinCruijssen Ну, мне все равно, что за персонаж, так как я беру только длину; в Retina 1 вы получаете некоторое _время $*в более ранних версиях Retina по умолчанию 1.
Нил

Ах я вижу. Ваш исходный код принимал все <как одиночное совпадение и повторял их в 10 раз больше (количество <в матче), и мое предлагаемое изменение повторяется каждые <отдельно 10 раз (что вы играли на 2 байта больше, используя неявную 1 с 10*). Теперь я лучше понимаю, почему это +было изначально. Я не знаю слишком много о встроенных функциях Retina, только регулярные выражения в целом, поэтому я предложил изменение, потому что я уже читал его как повторение каждые >10 раз. ;)
Кевин Круйссен

2

Bash (с sed и dc), 50 байтов

sed 's/</A+/g
s/T/1+/g
s/ /60*/g
s/\\//g'|dc -ez?p

Принимает разделенный пробелами ввод stdin, выводит вstdout

Попробуйте онлайн!

объяснение

Использует sed для преобразования ввода с кучей совпадений регулярных выражений, например, до <<<TT \ TTTTтех пор, пока ввод не будет преобразован в A+A+A+1+1+60*60*1+1+1+1+. Затем этот вход подается в dc с явной командой выполнения ввода ?, перед которой стоит z(помещает длину стека (0) в стек, чтобы у нас было где-то обосновать сложение), а затем p(print).





1

Древесный уголь , 26 байт

≔⁰θFS«≡ι ≦×⁶⁰θ<≦⁺χθT≦⊕θ»Iθ

Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:

≔⁰θ

Очистить результат.

FS«...»

Зацикливайте вводимые символы. Команда обернута в блок, чтобы не найти блок «по умолчанию».

≡ι

Переключить текущий персонаж ...

 ≦×⁶⁰θ

если это пробел, умножьте результат на 60 ...

<≦⁺χθ

если это <то добавить 10 к результату ...

T≦⊕θ

если это, Tто увеличивайте результат.

Iθ

Распечатайте результат.


1

R , 98 81 байт

(u=sapply(scan(,""),function(x,y=utf8ToInt(x))y%%3%*%(y%%6)))%*%60^(sum(u|1):1-1)

Попробуйте онлайн!

Смешно долго из-за разбора строки.Спасибо Giusppe за то, что он сбрил 16 ненужных байтов.

определять y значение байт-кода ввода Unicode иR = y("T<\") = y("𒐕𒌋𒑊")

Соблюдайте это R%%3 = 1,2,0иR%%6 = 1,5,0 ... такR%%3 * R%%6 = 1,10,0 !

Остальное легко: сумма на столбец, затем скалярное произведение с убывающей степенью 60.


Портирование asnwer Арно с использованием Reduce, вероятно, будет больше в гольфе.
JayCe

не scan(,"")разделяется на пробелы автоматически?
Джузеппе

1
хороший трюк с модами! Я пытался выяснить это, но не смог найти его ... и /60его можно заменить -1в выражении экспоненты для другого выключенного байта, плюс <-можно заменить на, =так как все в скобках.
Джузеппе

@Giuseppe Я попробовал %% 3, и это было многообещающе, поэтому я продолжал искать ... также использование точечного продукта только спасло мне еще один байт :)
JayCe

1

Рубин , 50 46 байтов

->a{x=0;a.bytes{|c|x+=[59*x,10,0,1][c%9%5]};x}

Попробуйте онлайн!

Базовый порт ответа Арнаулда улучшен на GB для -4 байтов.


1
45 байтов - фактически 47, если вы используете «байты» вместо «карты»
GB

Благодаря @GB, я, вероятно, остановлюсь на более длинной версии, поскольку восприятие входных данных в виде необработанных байт-кодов кажется слишком либеральным для языка, который обычно поддерживает строки.
Кирилл Л.

1
Еще один байт: 46 байт
GB


1

Java 8, 64 60 байт

a->{int r=0;for(int c:a)r+=c<33?r*59:c<63?10:84/c;return r;}

-4 байта благодаря @ceilingcat .

Попробуйте онлайн. Объяснение:

a->{            // Method with character-array parameter and integer return-type
  int r=0;      //  Result-integer, starting at 0
  for(int c:a)  //  Loop over each character `c` of the input-array
    r+=         //   Increase the result by:
       c<33?    //    Is the current character `c` a space:
        r*59    //     Increase it by 59 times itself
       :c<63?   //    Else-if it's a '<':
        10      //     Increase it by 10
       :c<85?   //    Else (it's a 'T' or '\'):
        84/c;   //     Increase it by 84 integer-divided by `c`,
                //     (which is 1 for 'T' and 0 for '\')
  return r;}    //  Return the result

0

Perl -F // -E, 39 байт

$w+=/</?10:/T/?1:/ /?59*$w:0for@F;say$w

Это читает номер для преобразования из STDIN.

Это существенно то же решение, которое было дано @Arnauld с использованием JavaScript.


0

F #, 128 байт

let s(v:string)=Seq.mapFoldBack(fun r i->i*Seq.sumBy(fun c->match c with|'<'->10|'T'->1|_->0)r,i*60)(v.Split ' ')1|>fst|>Seq.sum

Попробуйте онлайн!

Развернувшись, это будет выглядеть так:

let s (v:string) =
    Seq.mapFoldBack(fun r i ->
        i * Seq.sumBy(fun c ->
            match c with
                | '<' -> 10
                | 'T' ->1
                | _ -> 0
        ) r, 
        i * 60) (v.Split ' ') 1
    |> fst
    |> Seq.sum

Seq.mapFoldBackсочетает в себе Seq.mapи Seq.foldBack. Seq.mapFoldBackповторяет последовательность в обратном порядке и пропускает значение накопителя в последовательности (в этом случаеi ).

Для каждого элемента в последовательности вычисляется вавилонское число (с помощью Seq.sumByкоторого каждый символ отображается на число и суммируется результат), а затем умножается на i.iзатем умножается на 60, и это значение затем передается следующему элементу в последовательности. Начальное состояние для аккумулятора - 1.

Например, порядок вызовов и результатов Seq.mapFoldBackдля ввода <<<TT \ TTTTбудет:

(TTTT, 1)     -> (4, 60)
(\, 60)       -> (0, 3600)
(<<<TT, 3600) -> (115200, 216000)

Функция возвращает кортеж seq<int>, int. fstФункция возвращает первый элемент в этом наборе, иSeq.sum делает фактическое суммирование.

Почему бы не использовать Seq.mapiили подобное?

Seq.mapiсопоставляет каждый элемент в последовательности и предоставляет индекс для функции отображения. Оттуда вы могли бы сделать 60 ** index(где** находится оператор питания в F #).

Но **требует floats, нет ints, что означает, что вам нужно либо инициализировать, либо привести все значения в функцию как float. Вся функция вернетfloat , что (на мой взгляд) немного грязно.

С Seq.mapiего помощью можно сделать 139 байт :

let f(v:string)=v.Split ' '|>Seq.rev|>Seq.mapi(fun i r->Seq.sumBy(fun c->match c with|'<'->10.0|'T'->1.0|_->0.0)r*(60.0**float i))|>Seq.sum

0

Tcl , 134 байта

proc B l {regsub {\\} $l 0 l
lmap c [lreverse $l] {incr s [expr 60**([incr i]-1)*([regexp -all < $c]*10+[regexp -all T $c])]}
expr $s}

Попробуйте онлайн!

В обратном списке я зацикливаю приращение результата в подсчете <и T-all опцией regexp) и увеличиваю натуральное как степень 60.

Правильная версия (см. Комментарий)


Кажется, я потерпел неудачу из-за \ в последнем номере ... У меня должен был быть regsub {\\} $l0 lцикл перед foreach ....
Дэвид

0

APL (Dyalog Extended) , 18 байт SBCS

Функция анонимного молчаливого префикса.

60⊥10⊥¨≠'<T'∘⍧¨⍤⊆⊢

Попробуйте онлайн!

                  ⊢  the argument; "<<<TT \ TTTT"
       ≠             mask where different from space; [1,1,1,1,1,0,1,0,1,1,1,1]
                ⊆    enclose runs of 1; ["<<<TT","\","TTTT"]
               ⍤     on that
              ¨      for each one
             ⍧       Count the occurrences In it of the elements
            ∘        of the entire list
        '<T'         ["<","T"]; [[3,2],[0,0],[0,4]]
      ¨              for each one
   10⊥               evaluate as base-10 digits
60⊥                  evaluate as base-60 digits

0

05AB1E (legacy) , 10 байтов

#Ç9%5BO60β

Попробуйте онлайн!

#               # split input on spaces
 Ç              # convert each character to its codepoint
  9%            # modulo 9 (maps 𒌋 to 5, 𒐕 to 1, 𒑊 to 0)
    5B          # convert each to base 5 (5 becomes 10, 0 and 1 unchanged)
      O         # sum each column
       60β      # convert from base 60

05AB1E , 11 байт

#Ç9%5B€O60β

Попробуйте онлайн!

Тот же алгоритм, но в современном 05AB1E Oне работает со списками смешанных целых и списков, поэтому нам нужно €Oвместо этого.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.