Xkcd notasyonunda bir tarih okuyun


49

ISO 8601 standart tarih formatıyla ilgili xkcd'sinde Randall oldukça ilginç bir alternatif gösterime girdi:

görüntü tanımını buraya girin

Büyük sayılar, geçerli tarihte olağan sıralarında görünen tüm sayılardır ve küçük sayılar, bu sayının oluşumunun 1 temelli göstergeleridir. Bu yüzden yukarıdaki örnek temsil eder 2013-02-27.

Böyle bir tarih için bir ASCII gösterimi tanımlayalım. İlk satır 1 - 4 arasındaki endeksleri içerir. İkinci satır "büyük" rakamları içerir. Üçüncü satır, 5 ila 8 arasındaki endeksleri içerir. Tek bir yuvada birden fazla endeks varsa, bunlar en küçükten en büyüğe yan yana listelenir. mTek bir yuvada en çok endeks varsa (yani aynı basamakta ve aynı satırda), her sütun m+1geniş ve sola yaslı karakterlerden oluşmalıdır :

2  3  1  4
0  1  2  3  7
5     67    8

Tersine dönüşüm için eşlik eden meydan okumaya da bakın .

Meydan okuma

Xkcd notasyonunda bir tarih verildiğinde, karşılık gelen ISO 8601 tarihini ( YYYY-MM-DD) verin.

STDIN (veya en yakın alternatif), komut satırı argümanı veya işlev argümanı yoluyla giriş alarak ve sonucu STDOUT (veya en yakın alternatif), fonksiyon dönüş değeri veya function (out) parametresi ile çıktı alarak bir program veya işlev yazabilirsiniz.

Girişin, yıllar 0000ile 9999dahil olanlar arasında geçerli bir tarih olduğunu varsayabilirsiniz .

Girişte baştaki boşluklar olmayacak, ancak çizgilerin boşluklarla en fazla bir boşluk sütunu içeren bir dikdörtgene kadar doldurulduğunu varsayabilirsiniz.

Standart kuralları geçerlidir.

Test Kılıfları

2  3  1  4
0  1  2  3  7
5     67    8
2013-02-27

2  3  1     4
0  1  2  4  5
   5  67 8
2015-12-24

     1234
1    2
5678
2222-11-11

   1     3  24
0  1  2  7  8
57    6     8
1878-02-08

2   4   1   3
0   1   2   6
5       678
2061-02-22

      1 4 2 3
0 1 2 3 4 5 6 8
6 5 7         8
3564-10-28

1234
1
5678
1111-11-11

1 2 3 4
0 1 2 3
8 5 6 7
0123-12-30

11
Tarihi "kara kedi" biçiminde yazan insanlar benim varlığımın derdidir.
Carcigenicate

1
Cehaletimi affet, ama tuhaf format tam olarak tarihe ne kadar uyuyor? Hayatım boyunca kalıpları çözemiyorum.
Tom Carpenter

2
@ TomCarpenter Alt ve üst satır orta satırdaki sayıların tarihte nerede göründüğünü gösterir. Örneğin 1yukarıda 2, yani ilk rakam 2. 2yukarıda 0, yani ikinci rakam 0. 3yukarıda 1, 4yukarıda 3, bu yüzden 2013ilk dört hane olarak alıyoruz . Şimdi 5altındadır 0beşinci rakamdır yüzden 0, 6ve 7her ikisi de aşağıda 2, bu nedenle bu rakam her ikisi de 2. Ve nihayet, 8aşağıda 7, bu yüzden son rakam 8, ve son buluyoruz 2013-02-27. (Tireler xkcd notasyonunda örtüktür, çünkü hangi konumlarda göründüklerini biliyoruz.)
Martin Ender

Yanıtlar:


8

CJam, 35 bayt

ll{1$e>}*](l+eeWf%$-8>Wf=\f=2/(o'-*

Burada dene . Giriş hatlarının boşluklarla doldurulmasını bekler.

açıklama

lliki girdi satırı okur {1$e>}*ve ikincisinde bir "tarama" yapar: girişinin tüm öneklerini alır ve her öneki maksimumunu hesaplar. Giriş hattı için "0 1 2 7 8"bu iter "0001112227778". Yığımız şimdi şuna benziyor:

"first line" '0 '0 '0 '1 '1 '1 ...

Değerleri kullanarak kendimizi bir listeye yeniden yakalamamız gerekir ]; bu bizim ilk çizgimizi de yakalar, bu yüzden tekrar kullanmak (için dışarı çıkarız

"0001112227778" "first line"

beklenildiği gibi.

eelee+ bu satırı numaralandırır, ardından üçüncü bir giriş satırı için de aynı şeyi yapar ve sonuçları birleştirerek yığının üstüne şöyle bir şey bırakır:

[[0 '5] [1 ' ] [2 ' ] [3 ' ] [4 ' ] [5 ' ] [6 ' ] [7 ' ] [8 '6] [9 '7] [10 '8] [11 ' ] [12 ' ]
 [0 '2] [1 ' ] [2 ' ] [3 ' ] [4 '4] [5 ' ] [6 ' ] [7 ' ] [8 '1] [9 ' ] [10 ' ] [11 ' ] [12 '3]]

Şimdi bizim yığını ["0001112227778" X]nerede Xnumaralandırılmış liste üzerindedir.

Her çifti X( Wf%) içine çeviririz, çiftleri sözlüksel olarak sıralarız ( $) ve son 8 çifti bırakırız -8>. Bu bize şöyle bir şey verir:

[['1 8] ['2 0] ['3 12] ['4 4] ['5 0] ['6 8] ['7 9] ['8 10]]

Bu işe yarar, çünkü sıralama 'tüm basamakları anahtarla (boşluk) tüm basamakların önüne artan sırada yerleştirir.

Bunlar , birinci ve üçüncü satırlardaki karakterlerin " x -önerileri" dir: karakterleri 12345678yalnızca kendileriyle dikey olarak hizalanmış (değiştirilmiş) ikinci satırımızdan almamız gerekir.

Bunu yapmak için her pozisyonu ( Wf=), daha önce yaptığımız dizgiye indeks alıyoruz ( \f=). Biz "20610222"şimdi yığında: tire eklemek için, önce uzunluğunun iki (kesimler halinde bölünmüş 2/), bir satır (olmadan birinci segmenti baskı (o) ve tire kalan kesimleri katılmak ( '-*).

EDIT : harika tarama hilesi, Martin! Dört bayt kaydedildi.

EDIT 2 : eelee+ile değiştirerek iki bayt daha kurtardı l+ee; çizgiler hepsi aynı uzunluklarına sahip ve CJam liste indeksleme otomatik olarak liste uzunluğunu modulo, böylece endeksleri çünkü bu, işleri n+0, n+1, n+2... güzel eşleme 0, 1, 2...

EDIT 3 : Martin sürecin son adımında bir bayt daha kurtardı. Güzel!


6

Pyth, 48 43

j\-cj\-ctuuXN.xsTZK?qJhtHdKJ+hHeHGC.z*9d4 7

Test odası

Boşluklarla bir dikdörtgen içine doldurma gerektirir.

Bunun en iyi yaklaşım olduğunu düşünmüyorum, ancak temelde orta değeri, en üstte veya en altta gösterilen bir dizgede dizine yazar. Sanırım gördüğüm bariz şeylerin çoğunu golf oynamak için yeterli zamanım oldu. : P


4

JavaScript (ES7), 115

Anonim işlev Şablon dizgilerini kullanarak, anlamlı ve bayt sayımına dahil edilmiş yeni bir satır var.

Gereksinim: Orta giriş hattı ilkinden veya sondan daha kısa olamaz. Bu gereksinim, bir dikdörtgen oluşturmak için giriş boşluklarla doldurulduğunda yerine getirilir.

x=>([a,z,b]=o=x.split`
`,d=i=0,[for(c of z)o[a[i]-1]=o[b[i++]-1]=d=+c||d],o.splice(4,2,'-',o[4],o[5],'-'),o.join``)

Dizi anlama yerine .map kullanan ES6 sürüm 117

x=>([a,z,b]=o=x.split`
`,d=0,[...z].map((c,i)=>o[a[i]-1]=o[b[i]-1]=d=+c||d],o.splice(4,2,'-',o[4],o[5],'-'),o.join``)

Daha az golf oynadı

x=>(
  o=[],
  [a,z,b] = x.split`\n`,
  d=i=0,
  [ for(c of z) (
      d = +c||d, // each new digit found in z goes in d (but not the spaces and not the '0' (d starts at 0 anyway)
      o[a[i]-1] = o[b[i]-1] = d, // if the index char is space, that gives index -1 that is ignored when joining later
      ++i
  )],
  o.splice(4,2,'-',o[4],o[5],'-'), // add the dashes in the right places
  o.join``
)

Test pasajı

f=x=>(
  [a,z,b]=o=x.split`\n`,
  d=i=0,[for(c of z)o[a[i]-1]=o[b[i++]-1]=d=+c||d],
  o.splice(4,2,'-',o[4],o[5],'-'),o.join``
)


console.log=x=>O.textContent+=x+'\n';

[['2  3  1  4\n0  1  2  3  7\n5     67    8','2013-02-27']
,['2  3  1     4\n0  1  2  4  5\n   5  67 8','2015-12-24']
,['      1234\n1     2   \n5678','2222-11-11']
,['   1     3  24\n0  1  2  7  8 \n57    6     8','1878-02-08']
,['2   4   1   3\n0   1   2   6  \n5       678','2061-02-22']
,['      1 4 2 3\n0 1 2 3 4 5 6 8\n6 5 7         8','3564-10-28']
,['1234\n1   \n5678','1111-11-11']
,['1 2 3 4\n0 1 2 3\n8 5 6 7','0123-12-30']]
.forEach(t=>(k=t[1],r=f(t[0]),console.log(t[0]+'\n'+r+'\n'+(r==k?'OK\n':'Fail\n'))))
<pre id=O></pre>


Her iki zorluğu da çözen ilk kişi olduğunuz için tebrikler. :)
Martin Ender

3

Haskell, 125 106 103 bayt

a#' '=a
a#b=b
f i|[a,b,c]<-('-':)<$>lines i=[o|m<-"1234-56-78",(n,o,p)<-zip3 a(scanl1(#)b)c,m==n||m==p]

Tam bir dikdörtgene boşlukla doldurma gerektirir.

Kullanım örneği: f " 1 3 24\n0 1 2 7 8 \n57 6 8 "-> "1878-02-08".

Nasıl çalışır:

[a,b,c]<-('-':)<$>lines i          -- split input into lines, prepend a '-' to
                                   -- each, call them a, b and c
               (scanl1(#)b)        -- fill spaces of the middle line with the
                                   -- previous char, e.g.
                                   -- "-0  1  2  7  8 " -> "-00011122277788"
        zip3 a (scanl...) c        -- combine the lines element wise into triples.
                                   -- This is our lookup table for "1234-56-78" 
o|m<-"1234...",  (n,o,p)<-zip...,  m==n||m==p
                                   -- whenever m equals n or p (i.e. was originally
                                   -- in the first or last line), take the
                                   -- corresponding char o (middle line)

2

JavaScript ES6, 231

a=>{r=[];var b=[d,f,e]=a.split`
`.map(n=>n.split``);Array(Math.max(...b.map(n=>n.length))).fill().map((m,i)=>{(m=f[i])&&m!=" "&&(c=m);[d,e].map(m=>(g=m[i])&&g!=" "&&(r[g-1]=c))}),r.splice(4,0,"-"),r.splice(7,0,"-");return r.join``}

Test durumlarda .


1

Perl, 154 bayt

sub{$_=$_[1];@n=/\d/g;/ +/;map{map{$p[$i++].=$_}unpack"(a$+[0])*";$i=0}@_[0,2];map{map{$r[$_-1]=$n[$i]if/\d/}s plit$"='';$i++}@p;"@r"=~s/....\K(..)/-$1-/r}

Ungolfed ve açıkladı

sub{
    $_=$_[1]; # $_[1] is 2nd argument (i.e., 2nd line)
    @n=/\d/g; # @n now contains all digits in 2nd line
    / +/;     # $+[0] now the chunk length in 2nd line
              # Equivalent to /( +)/;$l = 1 + length $1;
    map{      # Perl golfer's for-loop
        map{ 
            $p[$i++] .= $_    # @p contains positions of each digit
        } unpack "(a$+[0])*"; # Split line into same chunk width
        $i=0 # At end of loop so we don't need $i=0 before next one
    } @_[0,2];# Outer map works on 1st and 3rd lines
    map{
        map{
            # Shove $n[$i] into ($_-1)th slot in @r if $_ is a number
            $r[$_-1] = $n[$i] if /\d/
        } split $"=''; # Equivalent to split '', but sets $"='' for free
        $i++
    }@p;
    # Concatenate @r, convert 20130227 to 2013-02-27, and return
    "@r"=~s/....\K(..)/-$1-/r
};

0

JavaScript (ES6), 131 bayt

s=>[...(r=[,,,,"-",,,"-"],l=s.split`
`)[1]].map((c,i)=>(c>"-"?n=c:0,y=+l[0][i],d=+l[2][i],y?r[y-1]=n:0,d?r[d+(d>6)]=n:0))&&r.join``

açıklama

Bir dikdörtgen oluşturmak için girişlerin boşluklarla doldurulması gerekir.

s=>
  [...(
    r=[,,,,"-",,,"-"], // r = array of result characters, prefill with "-" symbols
    l=s.split`
`                      // l = array of lines
  )[1]].map((c,i)=>(   // for each character on the middle line
    c>"-"?n=c:0,       // n = the most recent digit encountered
    y=+l[0][i],        // y = index on the year line at the current position
    d=+l[2][i],        // d = index on the date line at the current position
    y?r[y-1]=n:0,      // if y is a number, put n at the index y of the result
    d?r[d+(d>6)]=n:0   // if d is a number, put n at the index d (accounting for "-"s)
  ))
  &&r.join``           // return the result as a string

Ölçek


0

Powershell, 119 bayt

$r=,'-'*99
($a=$args-split'
')[1]|% t*y|%{if($_-32){$d=$_}
$a[0,2]|%{$r[$_[+$p]-48]=$d}
$p++}
-join$r[1..4+0+5+6+0+7+8]

Ungolfed test senaryosu:

$f = {

$r=,'-'*99                       # init a result as an array of '-' repeated 99 times
($a=$args-split"`n")[1]|% t*y|%{ # split argument string, store a top, middle and bottom to $a, then for each char of the middle line...
    if($_-32){$d=$_}             # store a digit to $d if the current character of the middle is not a space
    $a[0,2]|%{                   # for the top and the bottom lines...
        $r[$_[+$p]-48]=$d        # store a digit to the result array
    }                            # Note: if char in the current position is a space, then expression $_[+$p]-48 less then 0.
                                 # In this case, the expression $r[32-48]=$d changes unused element in a end of the array.
                                 # That is why the array was created by a large.
    $p++                         # next position
}
-join$r[1..4+0+5+6+0+7+8]        # return joined char with specified numbers
                                 # Note: element with index 0 has value '-'
}

@(
,(@"
2  3  1  4   
0  1  2  3  7
5     67    8
"@,"2013-02-27")

,(@"
2  3  1     4
0  1  2  4  5
    5  67 8  
"@,"2015-12-24")

,(@"
     1234
1    2   
5678     
"@,"2222-11-11")

,(@"
1     3  24
0  1  2  7  8 
57    6     8 
"@,"1878-02-08")

,(@"
2   4   1   3
0   1   2   6
5       678  
"@,"2061-02-22")

,(@"
      1 4 2 3  
0 1 2 3 4 5 6 8
6 5 7         8
"@,"3564-10-28")

,(@"
1234
1   
5678
"@,"1111-11-11")

,(@"
1 2 3 4
0 1 2 3
8 5 6 7
"@,"0123-12-30")

) | % {
    $a,$expected = $_
    $result = &$f $a
    "$(""$result"-eq"$expected"): $result"
}

Çıktı:

True: 2013-02-27
True: 2015-12-24
True: 2222-11-11
True: 1878-02-08
True: 2061-02-22
True: 3564-10-28
True: 1111-11-11
True: 0123-12-30

0

Jöle , 38 bayt

Ỵṙ-Zn⁶Ṫ€œṗƊḊZḟ⁶V€$€;2/p/Ʋ€ẎṢṪ€s2Ḣ;jɗ”-

Çevrimiçi deneyin!

Yardımcı yalnızca girişi kolaylaştırmak için oradadır; bu aslında tam bir programdır. Aşağıdakilere dikkat ettiğinizden emin olun :

  • İlk ve son satırlar ( ''') ve yanlarındaki satırlar ( netlik için orada boş).
    • Gerçek giriş formatı ikinci ve sondan fazla boş satırlara sahip değildir ve dize, aralarında yeni bir satır olmadan, tırnakların hemen yanında başlar ve biter:
      '' '1 3 24
      0 1 2 7 8 
      57 6 8 '' '
      Bu formatı kullanırken altbilgiyi bırakabilirsiniz. Bu gerçekten bir Python çok satırlı dizedir ve bazı girdiler için tırnak işaretleri gereklidir.
  • Girdiyi arka boşluklarla doldurun! Doğru dolgulu giriş olmadan herhangi bir doğru çıktı tamamen tesadüfidir ve benim tarafımdan onaylanmamaktadır.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.