Hitung Seperti Babel


41

Tantangan

Diberikan representasi ASCII dari nomor Babel sebagai input, output angka dalam angka Arab Barat.

Sistem Angka Babilonia

Bagaimana orang Babilonia menghitung? Menariknya, mereka menggunakan sistem Base 60 dengan elemen sistem Base 10. Pertama mari kita perhatikan kolom unit sistem:

Bangsa Babilonia hanya memiliki tiga simbol: T(atau, jika Anda dapat menerjemahkannya:) 𒐕yang mewakili 1, dan <(atau, jika Anda dapat menerjemahkannya:) 𒌋yang mewakili 10, dan \(atau, jika Anda menerjemahkannya:) 𒑊yang mewakili nol.

Catatan: Secara teknis, \(atau 𒑊) bukan nol (karena orang Babel tidak memiliki gagasan 'nol'). 'Nol' ditemukan kemudian, demikian \juga simbol placeholder ditambahkan kemudian untuk mencegah ambiguitas. Namun, untuk keperluan tantangan ini, cukup untuk dianggap \sebagai nol

Jadi, di setiap kolom Anda hanya menambahkan nilai simbol, misalnya:

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

Tidak akan ada lebih dari lima <atau lebih dari sembilan Tdi setiap kolom. \akan selalu muncul sendiri di kolom.

Sekarang, kita perlu memperluas ini untuk menambahkan lebih banyak kolom. Ini bekerja persis sama dengan basis enam puluh lainnya, di mana Anda mengalikan nilai kolom paling kanan dengan , yang ke kiri dengan 60 1 , yang ke kiri dengan 60 2 dan seterusnya. Anda kemudian menjumlahkan nilai masing-masing untuk mendapatkan nilai angka.600601602

Kolom akan dipisahkan oleh spasi untuk mencegah ambiguitas.

Beberapa contoh:

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

Aturan

  • Anda bebas menerima input ASCII ( T<\) atau input Unicode ( 𒐕𒌋𒑊)
  • Nomor yang dimasukkan akan selalu di bawah 107
  • The <s akan selalu ke kiri Ts di setiap kolom
  • \ akan selalu muncul sendiri di kolom

Kemenangan

Kode terpendek dalam byte menang.


2
@TaylorScott Ya, Anda dapat
Beta Decay

2
Dalam hal ini membantu: Max yang perlu ditangani adalah 4 kolom:<<<<TTTTTT <TTTTTTT <<<<TTTTTT <<<<
Wernisch

1
Apakah kolom selalu dipisahkan oleh masing-masing satu ruang ? Saya perhatikan jawaban bergantung padanya.
KRyan

4
Jenis asing dengan pipa hookah mengatakan Ay oh whey oh, ay oh whey oh - Hitung seperti orang Babel. Besar. Sekarang itu terjebak di kepalaku.
cobaltduck

5
"How did the Babylonians count? Interestingly, they used a Base 60 system with an element of a Base 10 system."Yang masih digunakan sampai sekarang; sistem angka Babel persis seperti yang kita gunakan untuk jam. Dua digit desimal masing-masing selama detik, menit, dan jam, 60 detik ke menit, 60 menit ke jam.
Ray

Jawaban:


39

JavaScript (ES6), 44 byte

Mengambil input sebagai array karakter ASCII.

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

Cobalah online!

Bagaimana?

Sistem Angka Babilonia dapat dilihat sebagai bahasa 4-instruksi yang bekerja dengan satu register - sebut saja akumulator.

Dimulai dengan , setiap karakter c dalam larik input a memodifikasi akumulator k sebagai berikut:k=0cak

  • space: kalikan dengan 60 (diimplementasikan sebagai: tambahkan 59 k ke k )k6059kk
  • <: tambahkan ke k10k
  • T: increment k
  • \: tidak melakukan apapun; ini adalah NOPinstruksi dari bahasa ini (diimplementasikan sebagai: tambah hingga k )0k


11

Perl 6 , 39 byte

-3 byte terima kasih kepada nwellnhof

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

Cobalah online!

Menggunakan karakter paku.

Penjelasan:

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

Anda mengalahkan saya beberapa menit. Inilah yang saya datang dengan: {:60[.words>>.&{sum (.ords X%151)X%27}]}(40 byte)
nwellnhof

@wellwell Dilakukan dengan sangat baik! Bagaimana Anda menemukan nilai mod?
Jo King

2
Cukup dengan kekerasan.
nwellnhof

11

Jelly ,  13  12 byte

ḲO%7C%13§ḅ60

Tautan monadik yang menerima daftar karakter yang menghasilkan bilangan bulat.

Cobalah online!

Bagaimana?

Ḳ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

Lain 12: ḲO⁽¡€%:5§ḅ60( ⁽¡€adalah 1013, jadi ini modulos 1013dengan Onilai-nilai rdinal mendapatkan 53, 5dan 1untuk <, T, \masing-masing kemudian melakukan bilangan bulat divisi, :dengan 5mendapatkan 10, 1dan 0)


Lol, saya sudah menghapus jawaban saya persis karena ini, karena saya ingat saya bisa menggunakan konversi basis tetapi secara harfiah terlalu malas untuk mencari tahu caranya. +1
Tn. Xcoder

6

05AB1E , 13 byte

8740|Ç%4/O60β

Cobalah online!

Untuk menebus betapa malasnya saya dengan jawaban Jelly saya, berikut ini adalah kiriman di 05AB1E xD.


Bantu 05AB1E-ers di luar sana, bukankah ada cara untuk mengompres angka seperti 8740?
Tn. Xcoder

2
codegolf.stackexchange.com/a/166851/52210 Sayangnya itu tidak akan lebih pendek: •Yη•(4 byte)
Kevin Cruijssen

2
@KevinCruijssen Terima kasih! Jawaban itu sangat berguna, saya akan benar-benar menggunakannya di masa depan
Tn. Xcoder

1
Senang ujungnya berguna. :) Saya menemukan hal-hal ini setelah melihat beberapa jawaban menggunakannya. Bagian kamus dijelaskan di sini . Dan kompresi string lain atau bilangan bulat besar saya tahu sendiri setelah melihat contoh terkait jawaban untuk "angsa" dan 246060 .
Kevin Cruijssen

1|Ç7%-13%O60βjuga 13 - apakah golf?
Jonathan Allan

6

Python 2 , 96 93 87 85 byte

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

Cobalah online!


Disimpan:

  • -1 byte, terima kasih kepada Tn. Xcoder
  • -4 byte, terima kasih untuk Poon Levi
  • -2 byte, terima kasih kepada Matthew Jensen

1
95:(ord(c)%5/2or 11)-1
Tn. Xcoder

@ Mr.Xcoder Terima kasih :)
TFeld

2
87:8740%ord(c)/4
Poon Levi

-2 dengan menghapus tanda kurung di sekitar jumlah kedua () Coba online!
Matthew Jensen

@MatthewJensen Terima kasih :)
TFeld

4

Excel VBA, 121 byte

Terbatas untuk Office 32-Bit yang ^berfungsi sebagai LongLongtipe literal dalam versi 64-Bit

Membawa input dari sel A1dan output ke jendela langsung 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

Tidak Disatukan dan Dikomentari

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 byte

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

Cobalah online!

Edit: -3 byte terima kasih kepada ngn

'\ T<'⍳mengganti karakter dengan angka (posisinya di string konstan), dan membalikkan input sehingga 'digit' yang paling signifikan adalah yang terakhir. Hal ini memungkinkan +\2=untuk menjaga hitungan berjalan dari kekuatan yang diinginkan dari 60 (diterapkan oleh 60*) dengan menghitung berapa kali spasi (indeks 2 dalam konstanta string) ditemui.

⌊10*⍵-3memberikan kekuatan sepuluh yang diinginkan untuk setiap karakter. Urutan karakter dalam konstanta string dan -3 offset menyebabkan '\' dan ruang untuk pergi ke angka negatif, menghasilkan pecahan ketika karakter tersebut dinaikkan ke kekuatan 10, yang memungkinkan mereka dihilangkan oleh .

Yang harus kita lakukan sekarang adalah mengalikan kekuatan-dari-10 digit dengan nilai-nilai kekuatan-dari-60 tempat dan menjumlahkannya +/.


simpan beberapa byte dengan menghindari perbandingan terpisah dengan ' ':{+/(⌊10*⍵-3)×60*+\2=⍵}'\ T<'⍳⌽
ngn


3

Kanvas , 20 17 16 byte

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

Coba di sini!

Penjelasan:

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 karakter, 56 byte

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

beberapa tes dengan jenis cek:

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

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

Setiap jenis hasil adalah angka.


2

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

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

Cobalah online!

Saya sedikit terobsesi dengan operasi array "gaya fungsional", menggunakan input ASCII, sejauh yang saya tahu, JS tidak terlalu pandai mendapatkan kode-kode golfily

Saya menyimpan ini untuk anak cucu, tetapi ini adalah solusi yang naif / bodoh, saya sarankan Anda memeriksa jawaban Arnauld yang jauh lebih menarik dari implementasi tantangan


@ Shaggy sepertinya bekerja untuk saya!
Skidsdev

c<'T'bekerja di tempatc=='<'
Tn. Xcoder

Simpan 1 lagi dengan mengganti &&dengan |.
Shaggy

@Shaggy dan simpan lebih banyak dengan menggunakan for...ofloop: P
ASCII-only

2

Retina , 29 26 23 byte

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

Cobalah online! Menggunakan pemisahan baris baru, tetapi tautan menyertakan tajuk untuk menggunakan spasi sebagai gantinya untuk kenyamanan. Sunting: Disimpan 3 byte dengan bantuan dari @KevinCruijssen. Menyimpan 3 byte lebih lanjut berkat @FryAmTheEggman. Penjelasan:

<
10*T

Ganti masing <- masing dengan 10 Tdetik.

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

Ambil baris pertama, kalikan dengan 60, dan tambahkan baris berikutnya. Kemudian ulangi sampai hanya ada satu baris yang tersisa.

T

Hitung Ts.

Versi 51 byte yang lebih cepat:

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

Cobalah online! Menggunakan pemisahan baris baru, tetapi tautan menyertakan tajuk untuk menggunakan spasi sebagai gantinya untuk kenyamanan. Penjelasan:

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

Cocokkan setiap baris satu per satu, dan hitung jumlah Ts dan 10 kali jumlah <s. Ini mengubah setiap baris menjadi nilai "digit" basis-60.

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

Basis konversi 60, menjalankan baris pada suatu waktu. Perhitungan dilakukan dalam desimal untuk kecepatan.


Saya cukup yakin baris ketiga bisa saja <tanpa +, kecuali saya tidak melihat semacam tepi case.
Kevin Cruijssen

1
@KevinCruijssen Bahkan lebih baik, seperti $&sekarang selalu satu karakter, saya dapat menggunakan karakter default, menyimpan dua byte lebih lanjut!
Neil

Ah bagus! :) Tidak tahu itu bisa dilakukan secara implisit untuk karakter tunggal.
Kevin Cruijssen

@KevinCruijssen Yah, saya tidak peduli apa karakternya, karena saya hanya mengambil panjangnya; di Retina 1 Anda mendapatkan waktu _lama $*di versi Retina default sebelumnya 1.
Neil

Ah, begitu. Kode awal Anda mengambil semua <sebagai pertandingan tunggal dan ulangi 10 kali panjangnya (jumlah <dalam pertandingan), dan perubahan yang saya usulkan berulang setiap <10 kali secara terpisah (yang telah Anda golf 2 byte lebih banyak menggunakan implisit 1 dengan 10*). Sekarang saya lebih mengerti mengapa +awalnya ada di sana. Saya tidak tahu terlalu banyak tentang Retina builtins, hanya regex secara umum, maka perubahan yang saya usulkan karena saya sudah membacanya berulang setiap >10 kali. ;)
Kevin Cruijssen

2

Bash (dengan sed dan dc), 50 byte

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

Membawa input yang dibatasi ruang stdin, dari menjadistdout

Cobalah online!

Penjelasan

Menggunakan sed untuk mengubah input dengan sekelompok kecocokan ekspresi reguler hingga, misalnya, input <<<TT \ TTTTtelah ditransformasikan menjadi A+A+A+1+1+60*60*1+1+1+1+. Kemudian input ini diumpankan ke dc dengan perintah eksekusi input eksplisit ?, didahului oleh z(mendorong panjang stack (0) ke stack sehingga kita memiliki tempat untuk menambahkan tambahan) dan diikuti oleh p(cetak).





1

Arang , 26 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

≔⁰θ

Kosongkan hasilnya.

FS«...»

Ulangi karakter input. The perintah dibungkus dalam blok untuk mencegah menemukan "default" blok.

≡ι

Beralih dari karakter saat ini ...

 ≦×⁶⁰θ

jika itu spasi maka kalikan hasilnya dengan 60 ...

<≦⁺χθ

jika a <maka tambahkan 10 ke hasilnya ...

T≦⊕θ

jika itu Tmaka kenaikan hasilnya.

Iθ

Cetak hasilnya.


1

R , 98 81 byte

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

Cobalah online!

Sangat panjang karena penguraian string. Terima kasih Giusppe untuk mencukur 16 byte yang tidak perlu.

Tentukan ynilai bytecode dari input unicode danR = y("T<\") = y("𒐕𒌋𒑊")

Amati itu R%%3 = 1,2,0dan R%%6 = 1,5,0... jadi R%%3 * R%%6 = 1,10,0!

Sisanya mudah: jumlah per kolom, kemudian produk-titik dengan kekuatan menurun 60.


Porting asnwer Arnauld menggunakan Reduce cenderung lebih golf.
JayCe

tidak scan(,"")terpecah pada spasi secara otomatis?
Giuseppe

1
trik yang bagus dengan mod, meskipun! Saya mencoba untuk mencari tahu tapi tidak bisa menemukannya ... dan /60dapat diganti dengan -1ekspresi eksponen untuk byte lain, ditambah <-dapat diganti oleh =karena itu semua di dalam tanda kurung.
Giuseppe

@ Giuseppe Saya mencoba %% 3 dan itu menjanjikan jadi saya terus mencari ... juga menggunakan produk titik hanya menyelamatkan saya satu byte tambahan :)
JayCe

1

Ruby , 50 46 byte

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

Cobalah online!

Port dasar jawaban Arnauld ditingkatkan oleh GB untuk -4 byte.


1
45 byte -bahkan 47 jika Anda menggunakan "byte" dan bukannya "peta"
GB

Terima kasih @GB, saya mungkin akan tetap menggunakan versi yang lebih panjang, karena mengambil input sebagai bytecodes mentah terasa agak terlalu liberal untuk bahasa yang biasanya mendukung string.
Kirill L.

1
Off byte lain: 46 byte
GB


1

Java 8, 64 60 byte

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

-4 byte terima kasih kepada @ceilingcat .

Cobalah online. Penjelasan:

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 byte

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

Ini membaca nomor yang akan dikonversi dari STDIN.

Ini penting untuk solusi yang sama seperti yang diberikan oleh @Arnauld menggunakan JavaScript.


0

F #, 128 byte

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

Cobalah online!

Ungolfed akan terlihat seperti ini:

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.mapFoldBackmenggabungkan Seq.mapdan Seq.foldBack. Seq.mapFoldBackiterates melalui urutan mundur, dan utas nilai akumulator melalui urutan (dalam hal ini, i).

Untuk setiap elemen dalam urutan, angka Babel dihitung (oleh Seq.sumBy, yang memetakan setiap karakter ke angka dan total hasilnya) dan kemudian dikalikan dengan i. ikemudian dikalikan dengan 60, dan nilai ini kemudian diteruskan ke item berikutnya dalam urutan. Keadaan awal untuk akumulator adalah 1.

Misalnya, urutan panggilan dan hasil Seq.mapFoldBackinput <<<TT \ TTTTadalah:

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

Fungsi akan mengembalikan tuple seq<int>, int. The fstmengembalikan fungsi item pertama dalam tuple itu, dan Seq.summelakukan penjumlahan yang sebenarnya.

Mengapa tidak menggunakan Seq.mapiatau serupa?

Seq.mapimemetakan setiap elemen dalam urutan, dan menyediakan indeks ke fungsi pemetaan. Dari sana Anda bisa melakukannya 60 ** index(di mana **operator daya di F #).

Tetapi **membutuhkan floats, tidak ints, yang berarti bahwa Anda perlu menginisialisasi atau melemparkan semua nilai dalam fungsi sebagai float. Seluruh fungsi akan mengembalikan a float, yang (menurut saya) agak berantakan.

Menggunakannya Seq.mapidapat dilakukan seperti ini untuk 139 byte :

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 byte

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}

Cobalah online!

Dalam daftar terbalik, saya loop menambah hasil dalam penghitungan <dan T(dengan -allopsi regexp) dan menambah kekuatan alami 60.

Versi yang benar (lihat komentar)


Sepertinya saya gagal yang satu ini, karena \ di angka terakhir ... Saya harus punya regsub {\\} $l0 lsebelum loop foreach ....
david

0

APL (Dyalog Extended) , 18 byte SBCS

Fungsi awalan diam-diam anonim.

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

Cobalah 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 (warisan) , 10 byte

#Ç9%5BO60β

Cobalah 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 byte

#Ç9%5B€O60β

Cobalah online!

Algoritma yang sama, tetapi di 05AB1E modern Otidak bekerja pada daftar int dan daftar campuran, jadi kita perlu €Osebagai gantinya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.