Cuenta como un babilonio

41

Reto

Dada una representación ASCII de un número babilónico como entrada, genera el número en números arábigos occidentales.

Sistema de numeración babilónico

¿Cómo contaban los babilonios? Curiosamente, utilizaron un sistema Base 60 con un elemento de un sistema Base 10. Consideremos primero la columna de unidad del sistema:

Los babilonios tenían solo tres símbolos: T(o, si puede representarlo:) 𒐕que representaba 1, y <(o, si puede representarlo:) 𒌋que representaba 10, y \(o, si 𒑊lo representaba:) que representaba cero.

Nota: Técnicamente, \(o 𒑊) no es cero (porque los babilonios no tenían la noción de 'cero'). 'Cero' se inventó más tarde, por lo que \se agregó un símbolo de marcador de posición más tarde para evitar la ambigüedad. Sin embargo, para los propósitos de este desafío, es suficiente considerar \como cero

Entonces, en cada columna solo sumas el valor de los símbolos, por ejemplo:

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

Nunca habrá más de cinco <o más de nueve Ten cada columna. \siempre aparecerá solo en la columna.

Ahora, necesitamos extender esto para agregar más columnas. Esto funciona exactamente igual que cualquier otra base sesenta, donde multiplica el valor de la columna más a la derecha por , el de la izquierda por , el de la izquierda por y así sucesivamente. Luego sumas el valor de cada uno para obtener el valor del número.60060 2601602

Las columnas estarán separadas por espacios para evitar la ambigüedad.

Algunos ejemplos:

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

Reglas

  • Usted es libre de aceptar la entrada ASCII ( T<\) o la entrada Unicode ( 𒐕𒌋𒑊)
  • El número ingresado siempre será inferior a107
  • Los <s siempre estarán a la izquierda de los Ts en cada columna
  • \ siempre aparecerá solo en una columna

Victorioso

El código más corto en bytes gana.

Decaimiento Beta
fuente
2
@TaylorScott Sí, puedes
Beta Decay
2
En caso de que ayude: Max que debe manejarse es de 4 columnas:<<<<TTTTTT <TTTTTTT <<<<TTTTTT <<<<
Wernisch
1
¿Las columnas siempre están separadas exactamente por un espacio cada una ? Noto respuestas confiando en ello.
KRyan
44
Los tipos extranjeros con las pipas de la cachimba dicen: ay, oh, suero, ay, ay, suero, oh: cuenta como un babilónico. Excelente. Ahora está atrapado en mi cabeza.
cobaltduck
55
"How did the Babylonians count? Interestingly, they used a Base 60 system with an element of a Base 10 system."Que todavía está en uso hoy; El sistema de números babilónico es exactamente lo que usamos para los relojes. Dos dígitos decimales cada uno para segundos, minutos y horas, 60 segundos para el minuto, 60 minutos para la hora.
Ray

Respuestas:

39

JavaScript (ES6), 44 bytes

Toma la entrada como una matriz de caracteres ASCII.

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

Pruébalo en línea!

¿Cómo?

El sistema de numeración babilónico se puede ver como un lenguaje de 4 instrucciones que funciona con un solo registro, llamémoslo acumulador.

Comenzando con , cada carácter en la matriz de entrada modifica el acumulador siguiente manera:c a kk=0cak

  • space: multiplique por (implementado como: agregue a )60 59 k kk6059kk
  • <: sumar ak10k
  • T: incrementok
  • \: hacer nada; esta es la NOPinstrucción de este lenguaje (implementado como: agregar a )k0k
Arnauld
fuente
12

C (gcc) , 140 138 136 bytes

B,a,b,y;l(char*o){y=B=0,a=1;for(char*n=o;*n;n++,B++[o]=b,a*=60)for(b=0;*n&&*n-32;n++)b+=*n-84?*n-60?:10:1;for(B=a;B/=60;y+=*o++*B);B=y;}

Pruébalo en línea!

Jonathan Frech
fuente
66
+1 Llevando "cuenta como un babyloniano" al siguiente nivel: D
Beta Decay
11

Perl 6 , 39 bytes

-3 bytes gracias a nwellnhof

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

Pruébalo en línea!

Utiliza los caracteres cuneiformes.

Explicación:

{                                     }   # 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
Jo King
fuente
Me ganaste por un par de minutos. Esto es lo que se me ocurrió: {:60[.words>>.&{sum (.ords X%151)X%27}]}(40 bytes)
nwellnhof
@nwellnhof ¡Muy bien hecho! ¿Cómo encontraste los valores mod?
Jo King
2
Simplemente por fuerza bruta.
nwellnhof
11

Jalea ,  13  12 bytes

ḲO%7C%13§ḅ60

Un enlace monádico que acepta una lista de caracteres que produce un número entero.

Pruébalo en línea!

¿Cómo?

Ḳ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

Otro 12: ḲO⁽¡€%:5§ḅ60( ⁽¡€es 1013, así que esto modulos 1013por los Ovalores rdinal conseguir 53, 5y 1para <, T, \respectivamente realiza entonces número entero división, :por 5conseguir 10, 1y 0)

Jonathan Allan
fuente
Lol, he eliminado mi respuesta exactamente por esto, ya que recordé que podía usar la conversión de base, pero literalmente era demasiado vago para averiguar cómo. +1
Sr. Xcoder
6

05AB1E , 13 bytes

8740|Ç%4/O60β

Pruébalo en línea!

Para compensar lo flojo que he sido con mi respuesta de Jelly, aquí hay una presentación en 05AB1E xD.

Sr. Xcoder
fuente
Ayuda 05AB1E-ers por ahí, ¿no había una manera de comprimir números como 8740?
Sr. Xcoder
2
codegolf.stackexchange.com/a/166851/52210 Lamentablemente no sería más corto: •Yη•(4 bytes)
Kevin Cruijssen
2
@KevinCruijssen ¡Gracias! Esa respuesta es muy útil, la
usaré
1
Me alegro de que la punta sea de utilidad. :) Resolví estas cosas después de ver algunas respuestas usándolas. La parte del diccionario se explicó aquí . Y la compresión de otras cadenas o enteros grandes me di cuenta después de ver las respuestas de ejemplo vinculadas para "ganso" y 246060 .
Kevin Cruijssen
1|Ç7%-13%O60βtambién es 13 - ¿es golfable?
Jonathan Allan
6

Python 2 , 96 93 87 85 bytes

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

Pruébalo en línea!


Salvado:

  • -1 byte, gracias al Sr. Xcoder
  • -4 bytes, gracias a Poon Levi
  • -2 bytes, gracias a Matthew Jensen
TFeld
fuente
1
95:(ord(c)%5/2or 11)-1
Sr. Xcoder
@ Mr.Xcoder Gracias :)
TFeld
2
87:8740%ord(c)/4
Poon Levi
-2 eliminando los paréntesis alrededor de la segunda suma () ¡ Pruébelo en línea!
Matthew Jensen
@MatthewJensen Gracias :)
TFeld
4

Excel VBA, 121 bytes

Restringido a Office de 32 bits, ya que ^sirve como el LongLongtipo literal en las versiones de 64 bits

Toma la entrada de la celda A1y las salidas a la ventana inmediata de 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

No golfista y 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
Taylor Scott
fuente
4

Dyalog APL , 33 30 bytes

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

Pruébalo en línea!

Editar: -3 bytes gracias a ngn

'\ T<'⍳reemplaza los caracteres con números (su posición en la cadena constante) e invierte la entrada para que los "dígitos" más significativos sean los últimos. Esto permite +\2=mantener una cuenta corriente de la potencia deseada de 60 (aplicada por 60*) contando la cantidad de veces que se encuentra un espacio (índice 2 en la cadena constante).

⌊10*⍵-3da el poder deseado de diez para cada personaje. El orden de los caracteres en la constante de cadena y el desplazamiento -3 hacen que '\' y el espacio pasen a números negativos, lo que resulta en fracciones cuando esos caracteres se elevan a la potencia de 10, lo que permite que sean eliminados por .

Todo lo que tenemos que hacer ahora es multiplicar los dígitos de potencias de 10 por los valores de posición de potencias de 60 y sumar el lote +/.

ratonera
fuente
ahorrar unos pocos bytes evitando la comparación independiente con ' ':{+/(⌊10*⍵-3)×60*+\2=⍵}'\ T<'⍳⌽
NGN
3

Lienzo , 20 17 16 bytes

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

Pruébalo aquí!

Explicación:

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
dzaima
fuente
3

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

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

alguna prueba con verificación de tipo:

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

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

Cada tipo de resultado es número.

RosLuP
fuente
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)

Pruébalo en línea!

Estoy un poco obsesionado con las operaciones de matriz de "estilo funcional", utiliza la entrada ASCII, por lo que puedo decir, JS no es muy bueno para obtener charfildes golfily

Lo guardo por el bien de la posteridad, pero esta es una solución ingenua / tonta, le sugiero que consulte la respuesta de Arnauld, que es mucho más interesante una implementación del desafío

Skidsdev
fuente
¡@Shaggy parece que me funciona!
Skidsdev
c<'T'trabaja en lugar dec=='<'
Sr. Xcoder
Ahorre 1 más reemplazando &&con |.
Shaggy
@Shaggy y ahorre mucho más usando for...ofbucles: P
Solo ASCII
2

Retina , 29 26 23 bytes

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

Pruébalo en línea! Utiliza separación de línea nueva, pero el enlace incluye encabezado para usar espacios en su lugar por conveniencia. Editar: Guardado 3 bytes con ayuda de @KevinCruijssen. Ahorró otros 3 bytes gracias a @FryAmTheEggman. Explicación:

<
10*T

Reemplace cada uno <con 10 Ts.

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

Tome la primera línea, multiplíquela por 60 y agregue la siguiente línea. Luego repita hasta que solo quede una línea.

T

Cuenta el Ts.

Versión más rápida de 51 bytes:

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

Pruébalo en línea! Utiliza separación de línea nueva, pero el enlace incluye encabezado para usar espacios en su lugar por conveniencia. Explicación:

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

Haga coincidir cada línea individualmente y cuente el número de Tsy 10 veces el número de <s. Esto convierte cada línea en su valor base de "dígitos" de 60.

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

Conversión de base 60, ejecutando una línea a la vez. El cálculo se realiza en decimal para la velocidad.

Neil
fuente
Estoy bastante seguro de que la tercera línea puede estar <sin ella +, a menos que no esté viendo algún tipo de caso límite.
Kevin Cruijssen
1
@KevinCruijssen Aún mejor, como $&ahora es siempre un carácter, ¡puedo usar el carácter predeterminado, ahorrando otros dos bytes!
Neil
¡Oh bien! :) No sabía que eso podría hacerse implícitamente para caracteres individuales.
Kevin Cruijssen
@KevinCruijssen Bueno, no me importa cuál sea el personaje, ya que solo estoy tomando la longitud; en Retina 1 obtienes un _tiempo $*en versiones anteriores de Retina por defecto 1.
Neil
Ah, ya veo. Su código inicial tomaba todo <como un solo partido y los repite 10 veces la longitud (la cantidad de <en el partido), y mi cambio propuesto se repite cada <10 veces por separado (que ha jugado 2 bytes más usando el 1 implícito con 10*) Ahora entiendo mejor por qué +estaba allí inicialmente. No sé demasiado sobre las retinas incorporadas, solo expresiones regulares en general, de ahí mi cambio propuesto porque ya lo leí como repetir cada >10 veces. ;)
Kevin Cruijssen
2

Bash (con sed y dc), 50 bytes

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

Toma entradas delimitadas por espacios desde stdin, salidas astdout

Pruébalo en línea!

Explicación

Utiliza sed para transformar la entrada con un montón de coincidencias de expresiones regulares hasta que, por ejemplo, la entrada <<<TT \ TTTTse haya transformado en A+A+A+1+1+60*60*1+1+1+1+. Luego, esta entrada se alimenta a dc con el comando de ejecución de entrada explícito ?, precedido por z(empuja la longitud de la pila (0) a la pila para que tengamos un lugar donde conectar la suma) y seguido por p(print).

Sophia Lechner
fuente
1

Carbón , 26 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

≔⁰θ

Borrar el resultado.

FS«...»

Pase sobre los caracteres de entrada. El comando está envuelto en un bloque para evitar que encuentre un bloque "predeterminado".

≡ι

Cambia el carácter actual ...

 ≦×⁶⁰θ

si es un espacio, multiplica el resultado por 60 ...

<≦⁺χθ

si es un, <entonces agregue 10 al resultado ...

T≦⊕θ

si es un, Tentonces incremente el resultado.

Iθ

Imprime el resultado.

Neil
fuente
1

R , 98 81 bytes

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

Pruébalo en línea!

Ridículamente largo debido al análisis de cadenas. Gracias Giusppe por reducir 16 bytes innecesarios.

Defina yel valor de bytecode de la entrada unicode yR = y("T<\") = y("𒐕𒌋𒑊")

Observa eso R%%3 = 1,2,0y R%%6 = 1,5,0... entonces R%%3 * R%%6 = 1,10,0!

El resto es fácil: suma por columna, luego producto de puntos con potencias decrecientes de 60.

JayCe
fuente
Portar la respuesta de Arnauld usando Reducir es probable que sea más golfoso.
JayCe
no se scan(,"")divide en espacios automáticamente?
Giuseppe
1
¡Buen truco con las modificaciones, sin embargo! Estaba tratando de resolver eso, pero no pude encontrarlo ... y /60puedo reemplazarlo -1en la expresión exponente para otro byte desactivado, además de que <-puede reemplazarse =ya que todo está entre paréntesis.
Giuseppe
@Giuseppe Probé %% 3 y fue prometedor, así que seguí buscando ... también usando un producto de punto solo me ahorró un byte adicional :)
JayCe
1

Ruby , 50 46 bytes

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

Pruébalo en línea!

Un puerto básico de la respuesta de Arnauld mejorado por GB para -4 bytes.

Kirill L.
fuente
1
45 bytes, en realidad 47 si usa "bytes" en lugar de "mapa"
GB
Gracias @GB, probablemente me quedaré con la versión más larga, ya que tomar la entrada como bytecodes sin formato se siente demasiado liberal para un lenguaje que normalmente admite cadenas.
Kirill L.
1
Otro byte desactivado: 46 bytes
GB
1

C (gcc) , 65 64 63 bytes

f(s,o)char*s;{for(o=0;*s;s++)o+=*s>32?(93^*s)/9:o*59;return o;}

Pruébalo en línea!

Curtis Bechtel
fuente
1
Reemplazar return ocon s=oguarda otros 5 bytes.
ErikF
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 gracias a @ceilingcat .

Pruébalo en línea. Explicación:

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
Kevin Cruijssen
fuente
0

Perl -F // -E, 39 bytes

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

Esto lee el número a convertir de STDIN.

Esta es la misma solución esencial dada por @Arnauld usando JavaScript.


fuente
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

Pruébalo en línea!

Ungolfed se vería así:

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.mapy Seq.foldBack. Seq.mapFoldBackitera a través de la secuencia hacia atrás, y pasa un valor de acumulador a través de la secuencia (en este caso, i).

Para cada elemento de la secuencia, se calcula el número de Babilonia (por Seq.sumBy, que asigna cada carácter a un número y suma el resultado) y luego se multiplica por i. iluego se multiplica por 60, y este valor se pasa al siguiente elemento de la secuencia. El estado inicial para el acumulador es 1.

Por ejemplo, el orden de las llamadas y los resultados Seq.mapFoldBackpara la entrada <<<TT \ TTTTsería:

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

La función devolverá una tupla de seq<int>, int. La fstfunción devuelve el primer elemento de esa tupla y Seq.sumrealiza la suma real.

¿Por qué no usar Seq.mapio similar?

Seq.mapiasigna cada elemento en la secuencia y proporciona el índice a la función de asignación. A partir de ahí, podría hacer 60 ** index(dónde **está el operador de energía en F #).

Pero **requiere floats, no ints, lo que significa que debe inicializar o convertir todos los valores en la función como float. Toda la función devolverá un float, que (en mi opinión) es un poco desordenado.

Usarlo Seq.mapise puede hacer así 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
Ciaran_McCarthy
fuente
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}

Pruébalo en línea!

En la lista invertida, realizo un bucle que incrementa el resultado en conteo <y T(con la -allopción regexp) e incrementa un natural como potencia de 60.

Versión correcta (ver comentario)

david
fuente
Parece que fallé este, debido a la \ en el último número ... Debería tener un regsub {\\} $l0 lantes del bucle foreach ...
David
0

APL (Dyalog Extended) , SBCS de 18 bytes

Función de prefijo tácito anónimo.

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

Pruébalo en línea!

                  ⊢  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
Adán
fuente
0

05AB1E (heredado) , 10 bytes

#Ç9%5BO60β

Pruébalo en línea!

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

Pruébalo en línea!

Mismo algoritmo, pero en el 05AB1E moderno Ono funciona en listas de entradas y listas mixtas, por lo que necesitamos en su €Olugar.

Mugriento
fuente