Conte como um babilônico


41

Desafio

Dada uma representação ASCII de um número babilônico como entrada, imprima o número em algarismos arábicos ocidentais.

Sistema Numérico da Babilônia

Como os babilônios contavam? Curiosamente, eles usaram um sistema Base 60 com um elemento de um sistema Base 10. Vamos primeiro considerar a coluna da unidade do sistema:

Os babilônios tinham apenas três símbolos: T(ou, se você pode renderizá-lo:), 𒐕que representava 1, e <(ou, se você pode renderizá-lo:), 𒌋que representava 10, e \(ou, se você renderizá-lo:), 𒑊que representava zero.

Nota: Tecnicamente, \(ou 𒑊) não é zero (porque os babilônios não tinham a noção de 'zero'). 'Zero' foi inventado mais tarde, assim \como um símbolo de espaço reservado adicionado mais tarde para evitar ambiguidade. No entanto, para os propósitos deste desafio, basta considerar \como zero

Então, em cada coluna você apenas adiciona o valor dos símbolos, por exemplo:

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

Nunca haverá mais que cinco <ou mais que nove Tem cada coluna. \sempre aparecerá sozinho na coluna.

Agora, precisamos estender isso para adicionar mais colunas. Isso funciona exatamente como qualquer outra base sessenta, onde você multiplica o valor da coluna mais à direita por , o da esquerda por , o da esquerda por e assim por diante. Você então adiciona o valor de cada um para obter o valor do número.60060 2601602

As colunas serão separadas por espaços para evitar ambiguidade.

Alguns exemplos:

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

Regras

  • Você é livre para aceitar entrada ASCII ( T<\) ou entrada Unicode ( 𒐕𒌋𒑊)
  • O número inserido sempre estará abaixo de107
  • Os <sempre estarão à esquerda dos Tem cada coluna
  • \ sempre aparecerá sozinho em uma coluna

Ganhando

O menor código em bytes vence.


2
@TaylorScott Sim, você pode
Decay Beta

2
Caso isso ajude: O máximo que precisa ser tratado é de 4 colunas:<<<<TTTTTT <TTTTTTT <<<<TTTTTT <<<<
Wernisch 13/08/18

1
As colunas são sempre separadas por exatamente um espaço cada ? Percebo respostas contando com isso.
KRyan

4
Tipos estrangeiros com cachimbos de narguilé dizem Ay oh whey oh, ay oh whey oh - Conte como um babilônico. Ótimo. Agora está preso na minha cabeça.
Cobaltduck 14/08/19

5
"How did the Babylonians count? Interestingly, they used a Base 60 system with an element of a Base 10 system."Que ainda está em uso hoje; o sistema numérico da Babilônia é exatamente o que usamos para relógios. Dois dígitos decimais para segundos, minutos e horas, 60 segundos para o minuto, 60 minutos para a hora.
Ray

Respostas:


39

JavaScript (ES6), 44 bytes

Recebe entrada como uma matriz de caracteres ASCII.

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

Experimente online!

Quão?

O Sistema Numérico da Babilônia pode ser visto como uma linguagem de quatro instruções que trabalha com um único registro - vamos chamá-lo de acumulador.

Começando com , cada caractere na matriz de entrada modifica o acumulador seguinte maneira:c a kk=0cak

  • space: multiplique por (implementado como: adicione a )60 59 k kk6059kk
  • <: adicione ak10k
  • T: incrementok
  • \: fazer nada; esta é a NOPinstrução deste idioma (implementada como: adicione a )k0k


11

Perl 6 , 39 bytes

-3 bytes graças a nwellnhof

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

Experimente online!

Usa os caracteres cuneiformes.

Explicação:

{                                     }   # 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

Você me venceu por alguns minutos. Aqui está o que eu vim com: {:60[.words>>.&{sum (.ords X%151)X%27}]}(40 bytes)
nwellnhof

@nwellnhof Muito bem feito! Como você encontrou os valores mod?
Jo rei

2
Simplesmente pela força bruta.
Nwellnhof 13/08/19

11

Geléia ,  13  12 bytes

ḲO%7C%13§ḅ60

Um link monádico que aceita uma lista de caracteres que gera um número inteiro.

Experimente online!

Quão?

Ḳ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

Outro 12: ḲO⁽¡€%:5§ḅ60( ⁽¡€é 1013, por isso este modulos 1013pelos Ovalores rdinal recebendo 53, 5e 1para <, T, \respectivamente, em seguida, executa inteiro divisão, :por 5chegar 10, 1e 0)


Lol, eu apaguei minha resposta exatamente por isso, desde que lembrei que podia usar a conversão de base, mas estava literalmente com preguiça de descobrir como. +1
Sr. Xcoder 13/08/19

6

05AB1E , 13 bytes

8740|Ç%4/O60β

Experimente online!

Para compensar o quão preguiçoso eu tenho com a minha resposta Jelly, aqui está uma submissão em 05AB1E xD.


Ajuda 05AB1E-lá fora, não havia uma maneira de comprimir números como 8740?
Mr. Xcoder

2
codegolf.stackexchange.com/a/166851/52210 Infelizmente não seria mais curta: •Yη•(4 bytes)
Kevin Cruijssen

2
@KevinCruijssen Thank you! Essa resposta é muito útil, vou usá-la totalmente no futuro.
Sr. Xcoder 13/08/18

1
Ainda bem que a ponta é útil. :) Eu descobri essas coisas depois de ver algumas respostas usando-as. A parte do dicionário foi explicada aqui . E a compactação de outras strings ou números inteiros grandes que eu descobri depois de ver o exemplo vinculado responde por "ganso" e 246060 .
Kevin Cruijssen

1|Ç7%-13%O60βtambém tem 13 anos - é jogável?
Jonathan Allan


4

Excel VBA, 121 bytes

Restrito ao Office de 32 bits, como ^serve como LongLongliteral de tipo nas versões de 64 bits

Leva a entrada da célula A1e sai para a janela imediata do 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

Sem Golfe e Comentado

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

Dyalog APL , 33 30 bytes

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

Experimente online!

Edit: -3 bytes graças a ngn

'\ T<'⍳substitui os caracteres por números (sua posição na constante da string) e inverte a entrada para que os 'dígitos' mais significativos sejam os últimos. Isso permite +\2=manter uma contagem 60*contínua da potência desejada de 60 (aplicada por ) contando o número de vezes que um espaço (índice 2 na constante da cadeia) é encontrado.

⌊10*⍵-3dá a potência desejada de dez para cada personagem. A ordem dos caracteres na constante da string e o deslocamento -3 fazem com que '\' e espaço passem para números negativos, resultando em frações quando esses caracteres são elevados à potência de 10, permitindo que sejam eliminados por .

Tudo o que precisamos fazer agora é multiplicar as potências de 10 dígitos pelos valores das potências de 60 e resumir o lote +/.


salve alguns bytes, evitando a comparação separada com ' ':{+/(⌊10*⍵-3)×60*+\2=⍵}'\ T<'⍳⌽
ngn


3

Tela , 20 17 16 bytes

S{{<≡AײT≡]∑]<c┴

Experimente aqui!

Explicação:

E{          ]     map over input split on spaces
  {       ]         map over the characters
   <≡A×               (x=="<") * 10
       ²T≡            x=="T"
           ∑        sum all of the results
             <c┴  and encode from base (codepoint of "<") to 10

3

APL (NARS ←io ← 0), 28 caracteres, 56 bytes

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

algum teste com verificação de tipo:

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

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

Cada resultado do tipo é número.


2

JavaScript (Node.js) , 122 114 107 106 83 bytes

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

Experimente online!

Estou um pouco obcecado com operações de matriz "estilo funcional", usa entrada ASCII, tanto quanto posso dizer, JS não é muito bom em obter códigos de golfe

Eu estou mantendo isso por causa da posteridade, mas essa é uma solução ingênua / burra, sugiro que você verifique a resposta de Arnauld, que é muito mais interessante na implementação do desafio


@ Shaggy parece que funciona para mim!
Skidsdev 13/08/19

c<'T'trabalha no lugar dec=='<'
Sr. Xcoder 13/08/19

Economize mais 1 substituindo &&por |.
Shaggy

@ Shaggy e economize muito mais usando for...ofloops: P
somente ASCII

2

Retina , 29 26 23 bytes

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

Experimente online! Usa separação de nova linha, mas o link inclui o cabeçalho para usar espaços, por conveniência. Editar: salvou 3 bytes com a ajuda de @KevinCruijssen. Economizei mais 3 bytes graças a @FryAmTheEggman. Explicação:

<
10*T

Substitua cada um <por 10 Ts.

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

Pegue a primeira linha, multiplique-a por 60 e adicione a próxima linha. Em seguida, repita até restar apenas uma linha.

T

Conte os Ts.

Versão mais rápida de 51 bytes:

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

Experimente online! Usa separação de nova linha, mas o link inclui o cabeçalho para usar espaços, por conveniência. Explicação:

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

Combine cada linha individualmente e conte o número de se T10 vezes o número de <s. Isso converte cada linha em seu valor "dígito" de base 60.

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

Conversão de base 60, executando uma linha por vez. O cálculo é feito em decimal para velocidade.


Tenho certeza de que a terceira linha pode ficar <sem a +, a menos que eu não esteja vendo algum tipo de caso extremo.
Kevin Cruijssen

1
@KevinCruijssen Ainda melhor, como $&agora é sempre um caractere, posso usar o caractere padrão, economizando mais dois bytes!
Neil

Ah legal! :) Não sabia que isso poderia ser feito implicitamente para caracteres únicos.
Kevin Cruijssen

@KevinCruijssen Bem, eu não ligo para o personagem, pois estou apenas estudando; na Retina 1, você fica um _tempo $*nas versões anteriores do Retina por padrão 1.
Neil

Ah entendo. Seu código inicial usava todas <as correspondências únicas e as repetia 10 vezes o comprimento (a quantidade <correspondente na correspondência), e minha alteração proposta é repetida a cada <10 vezes separadamente (que você gastou mais 2 bytes usando o 1 implícito com 10*) Agora eu entendo melhor porque o +estava lá inicialmente. Eu não sei muito sobre os retins internos da Retina, apenas regexes em geral, daí a minha alteração proposta porque eu já a li como repetida a cada >10 vezes. ;)
Kevin Cruijssen

2

Bash (com sed e dc), 50 bytes

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

Leva a entrada delimitada por espaço de stdin, produz parastdout

Experimente online!

Explicação

Usa sed para transformar a entrada com <<<TT \ TTTTvárias correspondências de expressões regulares até que, por exemplo, a entrada tenha sido transformada em A+A+A+1+1+60*60*1+1+1+1+. Em seguida, essa entrada é alimentada em dc com o comando explícito de execução de entrada ?, precedido por z(empurra o comprimento da pilha (0) para a pilha para que tenhamos algum lugar para fundamentar a adição) e seguido por p(imprimir).





1

Carvão , 26 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

≔⁰θ

Limpe o resultado.

FS«...»

Faça um loop sobre os caracteres de entrada. O comando é agrupado em um bloco para impedir que ele encontre um bloco "padrão".

≡ι

Alterne o caractere atual ...

 ≦×⁶⁰θ

se for um espaço, multiplique o resultado por 60 ...

<≦⁺χθ

se for um <, adicione 10 ao resultado ...

T≦⊕θ

se for um Tincremento do resultado.

Iθ

Imprima o resultado.


1

R , 98 81 bytes

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

Experimente online!

Ridiculamente longo devido à análise de string. Obrigado ao Giusppe por eliminar 16 bytes desnecessários.

Defina yo valor do bytecode da entrada unicode eR = y("T<\") = y("𒐕𒌋𒑊")

Observe isso R%%3 = 1,2,0e R%%6 = 1,5,0... então R%%3 * R%%6 = 1,10,0!

O resto é fácil: soma por coluna e produto pontual com potências decrescentes de 60.


Portar asnwer de Arnauld usando Reduce provavelmente será mais eficiente.
Jayce

não scan(,"")divide os espaços automaticamente?
Giuseppe

1
bom truque com os mods! Eu estava tentando descobrir isso, mas não consegui encontrá-lo ... e /60pode ser substituído -1na expressão expoente por outro byte desativado, além do que <-pode ser substituído por, =pois está tudo entre parênteses.
Giuseppe

@Giuseppe Tentei %% 3 e foi prometendo assim eu continuei olhando ... também usando um produto escalar apenas me salvou um byte adicional :)
Jayce

1

Ruby , 50 46 bytes

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

Experimente online!

Uma porta básica da resposta de Arnauld foi aprimorada em GB por -4 bytes.


1
45 bytes -Na verdade 47 se você usar "bytes" em vez de "mapa"
GB

Obrigado @GB, provavelmente continuarei com a versão mais longa, já que aceitar dados como bytecodes brutos parece um pouco liberal demais para um idioma que normalmente suporta strings.
22418 Kirill L.

1
Outro byte desativado: 46 bytes
GB


1

Java 8, 64 60 bytes

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

-4 bytes graças a @ceilingcat .

Experimente online. Explicação:

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 bytes

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

Lê o número a ser convertido de STDIN.

É essencial a mesma solução fornecida pelo @Arnauld usando JavaScript.


0

F #, 128 bytes

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

Experimente online!

Ungolfed ficaria assim:

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.mapFoldBackcombina Seq.mape Seq.foldBack. Seq.mapFoldBackitera pela sequência para trás e encadea um valor acumulador pela sequência (nesse caso i).

Para cada elemento da sequência, o número babilônico é calculado (por Seq.sumBy, que mapeia cada caractere para um número e totaliza o resultado) e depois multiplicado por i. ié então multiplicado por 60 e esse valor é passado para o próximo item na sequência. O estado inicial do acumulador é 1.

Por exemplo, a ordem das chamadas e os resultados Seq.mapFoldBackpara entrada <<<TT \ TTTTseria:

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

A função retornará uma tupla de seq<int>, int. A fstfunção retorna o primeiro item nessa tupla e Seq.sumfaz a soma real.

Por que não usar Seq.mapiou similar?

Seq.mapimapeia cada elemento na sequência e fornece o índice para a função de mapeamento. De lá, você poderia fazer 60 ** index(onde **está o operador de energia em F #).

Mas **exige floats, não ints, o que significa que você precisa inicializar ou converter todos os valores na função como float. Toda a função retornará a float, o que (na minha opinião) é um pouco confuso.

Usá- Seq.mapilo pode ser feito assim para 139 bytes :

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 bytes

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}

Experimente online!

Na lista invertida, faço um loop incrementando o resultado na contagem <e T(com a -allopção regexp) e incrementando uma potência natural como 60.

Versão correta (ver comentário)


Parece que eu não esta, por causa da \ no último número ... Eu deveria tinha um regsub {\\} $l0 lantes do loop foreach ....
david

0

APL (Dyalog Extended) , SBCS de 18 bytes

Função de prefixo tácito anônimo.

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

Experimente online!

                  ⊢  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 (herdado) , 10 bytes

#Ç9%5BO60β

Experimente online!

#               # 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 bytes

#Ç9%5B€O60β

Experimente online!

O mesmo algoritmo, mas no 05AB1E moderno Onão funciona em listas de entradas e listas mistas, por isso precisamos €O.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.