Compter comme un babylonien

41

Défi

Étant donné qu'une représentation ASCII d'un nombre babylonien en entrée, affiche le nombre en chiffres arabes occidentaux.

Système de numération babylonien

Comment les Babyloniens ont-ils compté? Fait intéressant, ils utilisaient un système Base 60 avec un élément d’un système Base 10. Considérons d’abord la colonne des unités du système:

Les Babyloniens n'avaient que trois symboles: T(ou, si vous pouvez le rendre:) 𒐕qui représente 1, et <(ou, si vous pouvez le rendre:) 𒌋qui représente 10, et \(ou, si vous le rendez:) 𒑊qui représente zéro.

Remarque: Techniquement, \(ou 𒑊) n'est pas nul (parce que les Babyloniens n'avaient pas la notion de «zéro»). "Zero" a été inventé plus tard, ainsi \qu'un symbole d'espace réservé a été ajouté plus tard pour éviter toute ambiguïté. Cependant, pour les besoins de ce défi, il suffit de considérer \que zéro

Donc, dans chaque colonne, vous ajoutez simplement la valeur des symboles, par exemple:

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

Il n'y aura jamais plus de cinq <ou plus de neuf Tdans chaque colonne. \apparaîtra toujours seul dans la colonne.

Maintenant, nous devons étendre cela à l’ajout de colonnes. Cela fonctionne exactement comme n'importe quelle autre base soixante, où vous multipliez la valeur de la colonne la plus à droite par , celle à gauche par , celle à gauche par , etc. Vous ajoutez ensuite la valeur de chacun pour obtenir la valeur du nombre.60060 2601602

Les colonnes seront séparées par des espaces pour éviter toute ambiguïté.

Quelques exemples:

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

Règles

  • Vous êtes libre d'accepter les entrées ASCII ( T<\) ou Unicode ( 𒐕𒌋𒑊).
  • Le nombre entré sera toujours inférieur àdix7
  • Le <s sera toujours à gauche du Ts dans chaque colonne
  • \ apparaîtra toujours seul dans une colonne

Gagnant

Le code le plus court en octets gagne.

Beta Decay
la source
2
@TaylorScott Oui, vous pouvez
Beta Decay
2
Si cela peut vous aider: Max doit être traité en 4 colonnes: <<<<TTTTTT <TTTTTTT <<<<TTTTTT <<<<
Wernisch
1
Les colonnes sont-elles toujours séparées par exactement un espace chacune ? Je remarque des réponses en fonction.
KRyan
4
Les types étrangers avec les narguilés disent Ay oh whey oh, ay oh whey oh - Comptez comme un babylonien. Génial. Maintenant, c'est coincé dans ma tête.
cobaltduck
5
"How did the Babylonians count? Interestingly, they used a Base 60 system with an element of a Base 10 system."Qui est encore en usage aujourd'hui; le système de numération babylonien est exactement ce que nous utilisons pour les horloges. Deux chiffres décimaux chacun pour les secondes, les minutes et les heures, de 60 secondes à la minute et de 60 minutes à l’heure.
Ray

Réponses:

39

JavaScript (ES6), 44 octets

Prend les entrées sous forme de tableau de caractères ASCII.

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

Essayez-le en ligne!

Comment?

Le système de chiffres babylonien peut être vu comme une langue à 4 instructions fonctionnant avec un seul registre - appelons-le l'accumulateur.

À partir de , chaque caractère c du tableau d'entrée a modifie l'accumulateur k comme suit:k=0cunek

  • space: multipliez par 60 (implémenté sous la forme: ajoutez 59 k à k )k6059kk
  • <: ajouter à kdixk
  • T: incrément k
  • \: ne fais rien; c'est l' NOPinstruction de ce langage (implémenté sous la forme: ajoutez à k )0k
Arnauld
la source
12

C (gcc) , 140 138 136 octets

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;}

Essayez-le en ligne!

Jonathan Frech
la source
6
+1 Prendre "compter comme un babylonien" au prochain niveau: D
Beta Decay
11

Perl 6 , 39 octets

-3 octets grâce à nwellnhof

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

Essayez-le en ligne!

Utilise les caractères cunéiformes.

Explication:

{                                     }   # 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
la source
Vous m'avez battu de quelques minutes. Voici ce que je suis venu avec: {:60[.words>>.&{sum (.ords X%151)X%27}]}(40 bytes)
nwellnhof
@nwellnhof Très bien fait! Comment avez-vous trouvé les valeurs mod?
Jo King
2
Simplement par la force brute.
nwellnhof
11

Gelée ,  13 à  12 octets

ḲO%7C%13§ḅ60

Un lien monadique acceptant une liste de caractères qui donne un entier.

Essayez-le en ligne!

Comment?

Ḳ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

Un autre 12: ḲO⁽¡€%:5§ḅ60( ⁽¡€est 1013, cette modulo 1013par les Ovaleurs rdinal obtenir 53, 5et 1pour <, T, \puis exécute respectivement division entière, :en 5obtenir 10, 1et 0)

Jonathan Allan
la source
Lol, j'ai supprimé ma réponse exactement à cause de cela, car je me souvenais que je pouvais utiliser la conversion de base, mais que j'étais littéralement trop paresseux pour savoir comment. +1
M. Xcoder
6

05AB1E , 13 octets

8740|Ç%4/O60β

Essayez-le en ligne!

Pour compenser ma paresse avec ma réponse à Jelly, voici une soumission dans 05AB1E xD.

M. Xcoder
la source
Aidez les 05AB1E-ers, n'y avait-il pas un moyen de compresser des nombres comme 8740?
M. Xcoder
2
codegolf.stackexchange.com/a/166851/52210 Malheureusement, il ne serait pas plus court: •Yη•(4 octets)
Kevin Cruijssen
2
@KevinCruijssen Merci! Cette réponse est très utile, je l'utiliserai totalement dans le futur
M. Xcoder
1
Heureux que le conseil soit utile. :) J'ai compris ces choses après avoir vu des réponses les utiliser. La partie dictionnaire a été expliquée ici . Et la compression d’autres chaînes ou de grands nombres entiers que j’ai moi-même calculés après avoir vu les exemples de réponses liées pour "goose" et 246060 .
Kevin Cruijssen
1|Ç7%-13%O60βest également 13 - est-ce golfable?
Jonathan Allan
6

Python 2 , 96 93 87 85 octets

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

Essayez-le en ligne!


Enregistré:

  • -1 octet, merci à M. Xcoder
  • -4 octets, merci à Poon Levi
  • -2 octets, merci à Matthew Jensen
TFeld
la source
1
95:(ord(c)%5/2or 11)-1
M. Xcoder
@ Mr.Xcoder Merci :)
TFeld
2
87:8740%ord(c)/4
Poon Levi
-2 en supprimant les parenthèses autour de la deuxième somme () Essayez-le en ligne!
Matthew Jensen
@MatthewJensen Merci :)
TFeld le
4

Excel VBA, 121 octets

Limité à Office 32 bits, qui ^sert deLongLong type littéral dans les versions 64 bits

Prend les entrées de la cellule A1et les sorties dans la fenêtre vbe immediate.

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 and Commented

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
la source
4

Dyalog APL , 33 à 30 octets

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

Essayez-le en ligne!

Edit: -3 octets grâce à ngn

'\ T<'⍳remplace les caractères par des nombres (leur position dans la constante de chaîne) et inverse l'entrée de sorte que les "chiffres" les plus significatifs soient les derniers. Cela permet +\2=de conserver un nombre actif de la puissance souhaitée de 60 (appliquée par 60*) en comptant le nombre de fois où un espace (index 2 dans la constante de chaîne) est rencontré.

⌊10*⍵-3donne la puissance désirée de dix pour chaque personnage. L'ordre des caractères dans la constante de chaîne et le décalage -3 font que '\' et l'espace passent à des nombres négatifs, ce qui crée des fractions lorsque ces caractères sont augmentés à la puissance de 10, ce qui permet de les éliminer .

Tout ce que nous avons à faire maintenant, c’est de multiplier les puissances de 10 chiffres par les valeurs de position de puissances de 60 et d’additionner le tout +/.

mousetrapper
la source
économisez quelques octets en évitant la comparaison séparée avec ' ':{+/(⌊10*⍵-3)×60*+\2=⍵}'\ T<'⍳⌽
ngn
3

Toile , 20 17 16 octets

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

Essayez-le ici!

Explication:

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
la source
3

APL (NARS io ← 0), 28 caractères, 56 octets

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

certains tests avec vérification de type:

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

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

Chaque type de résultat est un nombre.

RosLuP
la source
2

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

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

Essayez-le en ligne!

Je suis un peu obsédé par les opérations sur les tableaux de "style fonctionnel", utilise une entrée ASCII, autant que je sache, JS n'est pas très doué pour obtenir des codes de caractères fantaisistes

Je garde cela pour la postérité, mais c'est une solution naïve / idiote, je vous suggère de consulter la réponse d'Arnauld, qui est bien plus intéressante qu'une mise en œuvre du défi.

Skidsdev
la source
@Shaggy semble que cela fonctionne pour moi!
Skidsdev
c<'T'fonctionne à la place dec=='<'
M. Xcoder
Économisez 1 de plus en remplaçant &&par |.
Shaggy
@Shaggy et économisez beaucoup plus en utilisant des for...ofboucles: P
ASCII uniquement
2

Retina , 29 26 23 octets

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

Essayez-le en ligne! Utilise la séparation entre les lignes, mais link inclut un en-tête pour utiliser des espaces à des fins pratiques. Edit: 3 octets enregistrés avec l’aide de @KevinCruijssen. Sauvegardé de 3 octets supplémentaires grâce à @FryAmTheEggman. Explication:

<
10*T

Remplacer chacun <par 10 Ts.

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

Prenez la première ligne, multipliez-la par 60 et ajoutez la ligne suivante. Répétez ensuite jusqu'à ce qu'il ne reste qu'une ligne.

T

Compte le T s.

Version 51 octets plus rapide:

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

Essayez-le en ligne!Utilise la séparation entre les lignes, mais link inclut un en-tête pour utiliser des espaces à des fins pratiques. Explication:

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

Faites correspondre chaque ligne individuellement et comptez le nombre de Ts et 10 fois le nombre de< s. Ceci convertit chaque ligne en valeur "chiffre" en base 60.

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

Conversion en base 60, en exécutant une ligne à la fois. Le calcul est fait en décimal pour la vitesse.

Neil
la source
Je suis à peu près sûr que la troisième ligne peut être juste <sans le +, à moins que je ne voie pas une sorte de cas de bord.
Kevin Cruijssen
1
@KevinCruijssen Encore mieux, comme $&c'est toujours maintenant un caractère, je peux utiliser le caractère par défaut, en économisant deux octets supplémentaires!
Neil
Ah bien! :) Je ne savais pas que cela pouvait être fait implicitement pour des personnages isolés.
Kevin Cruijssen
@KevinCruijssen Eh bien, je me fiche de la nature du personnage, je ne fais que prendre de la longueur; Dans Retina 1, les versions précédentes de Retina prennent un _certain temps . $*1
Neil
Ah, je vois. Votre code initial prenait tous les éléments <comme une seule correspondance et les répétait 10 fois la longueur (la quantité <dans la correspondance), et ma modification proposée répète chaque <fois 10 fois séparément 10*) Maintenant, je comprends mieux pourquoi ils +étaient là au début. Je ne sais pas trop sur les commandes intégrées à Retina, seulement les expressions rationnelles en général, d’où le changement que je propose car je le lis déjà comme répétition toutes les >10 fois. ;)
Kevin Cruijssen
2

Bash (avec sed et dc), 50 octets

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

Prend des entrées délimitées par un espace de stdin, sorties àstdout

Essayez-le en ligne!

Explication

Sed utilise pour transformer l’entrée avec un tas de correspondances d’expressions régulières jusqu’à ce que, par exemple, l’entrée <<<TT \ TTTTait été transformée A+A+A+1+1+60*60*1+1+1+1+. Ensuite, cette entrée est alimentée en courant continu avec la commande d’exécution d’entrée explicite ?, précédée de z(insère la longueur de la pile (0) dans la pile de sorte que nous ayons un emplacement à la terre pour l’addition) et suivie de p(impression).

Sophia Lechner
la source
2

Dyalog APL, 35 32 octets

f←{⍵+('<T\ '⍳⍺)⌷10,1,0,59×⍵}/∘⌽0∘,

Essayez-le en ligne!

31 dans dzaima / APL

dzaima
la source
1

Charbon de bois , 26 octets

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

Essayez-le en ligne! Le lien est vers la version verbeuse du code. Explication:

≔⁰θ

Effacer le résultat.

FS«...»

Boucle sur les caractères saisis. La commande est encapsulée dans un bloc pour l'empêcher de trouver un bloc "par défaut".

≡ι

Basculez sur le personnage actuel ...

 ≦×⁶⁰θ

si c'est un espace, multipliez le résultat par 60 ...

<≦⁺χθ

si c'est un, <ajoutez 10 au résultat ...

T≦⊕θ

si c'est un Tincrémente alors le résultat.

Iθ

Imprimer le résultat.

Neil
la source
1

R , 98 81 octets

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

Essayez-le en ligne!

Ridiculement long en raison de l'analyse des chaînes.Merci Giusppe d’avoir supprimé 16 octets inutiles.

Définit yla valeur de bytecode de l’entrée unicode etR = y("T<\") = y("𒐕𒌋𒑊")

Observe ça R%%3 = 1,2,0et R%%6 = 1,5,0... alorsR%%3 * R%%6 = 1,10,0 !

Le reste est facile: somme par colonne, puis produit par points avec puissances décroissantes de 60.

JayCe
la source
Porter l’aide d’Arnauld à l’aide de Réduire sera probablement plus amusant.
JayCe
ne se scan(,"")divise pas automatiquement sur les espaces?
Giuseppe
1
belle astuce avec les mods, cependant! J'essayais de comprendre cela, mais je ne pouvais pas le trouver ... et je /60peux le remplacer par -1l'expression de l'exposant pour un autre octet, en plus du <-peut être remplacé par =puisque tout est entre parenthèses.
Giuseppe
@ Giuseppe, j'ai essayé %% 3 et c'était prometteur alors j'ai continué à chercher ... utiliser un produit scalaire m'a juste sauvé un octet supplémentaire :)
JayCe
1

Ruby , 50 46 octets

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

Essayez-le en ligne!

Un port de base de la réponse Arnauld amélioré de 4 octets par Go.

Kirill L.
la source
1
45 octets - effectivement 47 si vous utilisez "octets" au lieu de "carte"
GB
Merci @GB, je vais probablement m'en tenir à la version la plus longue, car prendre des entrées en tant que bytecodes bruts semble un peu trop libéral pour un langage qui prend normalement en charge les chaînes.
Kirill L.
1
Un autre octet: 46 octets
GB
1

C (gcc) , 65 64 63 octets

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

Essayez-le en ligne!

Curtis Bechtel
la source
1
Remplacer return opar s=oenregistre 5 octets supplémentaires.
ErikF
1

Java 8, 64 60 octets

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

-4 octets grâce à @ceilingcat .

Essayez-le en ligne. Explication:

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
la source
0

Perl -F // -E, 39 octets

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

Ceci lit le numéro à convertir de STDIN.

C'est essentiel la même solution que celle donnée par @Arnauld en utilisant JavaScript.


la source
0

F #, 128 octets

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

Essayez-le en ligne!

Ungolfed cela ressemblerait à ceci:

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.mapFoldBackcombine Seq.mapet Seq.foldBack. Seq.mapFoldBackitère dans la séquence vers l’arrière et enfile une valeur d’accumulateur dans la séquence (dans ce cas,i ).

Pour chaque élément de la séquence, le nombre babylonien est calculé (par Seq.sumByce qui mappe chaque caractère sur un nombre et totalise le résultat), puis multiplié par i.iest ensuite multiplié par 60 et cette valeur est ensuite transmise au prochain élément de la séquence. L'état initial de l'accumulateur est 1.

Par exemple, l'ordre des appels et des résultats en Seq.mapFoldBackentrée <<<TT \ TTTTserait:

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

La fonction retournera un tuple de seq<int>, int. La fstfonction retourne le premier élément de ce tuple et Seq.sumeffectue la somme réelle.

Pourquoi ne pas utiliser Seq.mapiou similaire?

Seq.mapimappe chaque élément de la séquence et fournit l'index à la fonction de mappage. À partir de là vous pourriez faire60 ** index (où** trouve l'opérateur électrique en F #).

Mais **requiert floats, pas ints, ce qui signifie que vous devez initialiser ou convertir toutes les valeurs de la fonction en tant quefloat . La fonction entière retournera unfloat , ce qui (à mon avis) est un peu désordonné.

En utilisant Seq.mapicela peut être fait comme ça pour 139 octets :

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
la source
0

Tcl , 134 octets

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}

Essayez-le en ligne!

Dans la liste inversée, je boucle en incrémentant le résultat en comptant <et T(avec-all option regexp) et incrémentant une puissance naturelle de 60.

Version correcte (voir commentaire)

david
la source
Il semble que j'ai échoué celui-ci, à cause du \ dans le dernier numéro ... Je devrais avoir un regsub {\\} $l0 lavant la boucle foreach ....
david
0

APL (Dyalog Extended) , SBCS 18 octets

Fonction de préfixe tacite anonyme.

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

Essayez-le en ligne!

                  ⊢  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
Adam
la source
0

05AB1E (hérité) , 10 octets

#Ç9%5BO60β

Essayez-le en ligne!

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

#Ç9%5B€O60β

Essayez-le en ligne!

Même algorithme, mais dans la version moderne 05AB1E One fonctionne pas avec les listes d’adresses et de listes mixtes, nous avons donc besoin de €Ocela.

Grimmy
la source