Przeczytaj tekst ASCII-Art


34

Inspirowany przez Golfa alfabet ASCII , którego wyzwanie jest (prawie) odwrotne.


Zadanie:

Weź ciąg tekstu ASCII-art i wyślij jego treść jako zwykły tekst ASCII.


Wkład:

Ciąg tekstu ASCII-art.

Dane wejściowe będą zawierać tylko wystąpienia znaku ASCII #, spacje oraz 4 lub 5 nowych linii (końcowy nowy znak jest opcjonalny). Wszystkie linie mają tę samą długość. (Oznacza to, że ostatnia litera ASCII-art jest wypełniona końcowymi spacjami). Możesz użyć innego drukowalnego znaku ASCII zamiast# na wejściu, jeśli chcesz.

Dane wejściowe będą zawierać litery A-ZASCII-art i spacje ASCII-art (blok 5 x 5 białych znaków). Bez interpunkcji. Jest tylko jeden wiersz tekstu ASCII-art (5 wierszy rzeczywistych). Nie będzie żadnych spacji ani wiodących przestrzeni ASCII-art, ani sąsiadujących przestrzeni ASCII-art.

Rozmiar liter to 5 x 5 znaków. Między każdą literą jest spacja 1x5. Odstęp między słowami to blok białych znaków 5x5 (+ 1x5 spacji po każdej stronie, ponieważ jest to tylko kolejna litera). Na końcu lub na początku nie będzie miejsca 1x5, tylko między literami ASCII-art.


Wydajność:

Ciąg zawierający tekst jako znaki ASCII A-Z+ spacje. Dane wyjściowe mogą być również pisane małymi literami, jeśli jest to w jakiś sposób łatwiejsze dla twojego rozwiązania. Dozwolone są również przypadki mieszane.


Litery ASCII-art:

 ###  ####   ###  ####  ##### #####  ###  #   # ##### ##### #   # #     #   #
#   # #   # #   # #   # #     #     #     #   #   #     #   #  #  #     ## ##
##### ####  #     #   # ####  ####  #  ## #####   #     #   ###   #     # # #
#   # #   # #   # #   # #     #     #   # #   #   #   # #   #  #  #     #   #
#   # ####   ###  ####  ##### #      ###  #   # ##### ###   #   # ##### #   #

#   #  ###  ####   ###  ####   ###  ##### #   # #   # #   # #   # #   # #####
##  # #   # #   # #   # #   # #       #   #   # #   # #   #  # #   # #     # 
# # # #   # ####  #   # ####   ###    #   #   #  # #  # # #   #     #     #  
#  ## #   # #     #  #  #   #     #   #   #   #  # #  ## ##  # #    #    #   
#   #  ###  #      ## # #   #  ###    #    ###    #   #   # #   #   #   #####

Przestrzeń:

     |
     | A 5x5 square of spaces.
     | (Padded with |s to make it appear in this post.)
     |
     |

Przykłady:

Wkład:

#   # ##### #     #      ###        #   #  ###  ####  #     #### 
#   # #     #     #     #   #       #   # #   # #   # #     #   #
##### ####  #     #     #   #       # # # #   # ####  #     #   #
#   # #     #     #     #   #       ## ## #   # #   # #     #   #
#   # ##### ##### #####  ###        #   #  ###  #   # ##### #### 

Wydajność: HELLO WORLD

Wkład:

 ###   ###   ###  ##### #####
#   # #     #   #   #     #  
#####  ###  #       #     #  
#   #     # #   #   #     #  
#   #  ###   ###  ##### #####

Wydajność: ASCII

Wkład:

####  ####   ###   ### 
#   # #   # #   # #    
####  ####  #     #  ##
#     #     #   # #   #
#     #      ###   ### 

Wydajność: PPCG


To jest , więc wygrywa najkrótsza odpowiedź w bajtach.


10
Myślę, że rozwiązaniem tego może być jakaś funkcja skrótu ...
Neil,

6
Bounty ode mnie, jeśli zrobisz to, przekształcając dane wejściowe w obraz i rozwiązując to za pomocą przetwarzania obrazu! (Oczywiście trzeba też zagrać w golfa)
Stewie Griffin,

3
Jeśli komukolwiek to pomoże: drugi wiersz, czwarty wiersz lub środkowa kolumna liter mogą zostać upuszczone bez utraty istotnych informacji.
Martin Ender,

1
@JungHwanMin Hmm. Myślę, że nie, ponieważ nie byłby to bardzo czytelny dla ludzi tekst ASCII-art.
Steadybox 07.04.17

1
@JonathanAllan Myślę, że to też byłoby w porządku.
Steadybox

Odpowiedzi:


13

Galaretka ,  50 44  42 bajtów

ỴZ;6/UOḂḅ7‘ị“¥ŒƲVĊ⁾|W£⁼³ƭÇuʋụzḢĖ0ḢẆẠØsĠỌỊ»

Wypróbuj online! (zauważ, że argument nie wymaga wiodącego nowego wiersza, ale ponieważ początkowe i końcowe nowe wiersze nie mają żadnego efektu, umieściłem jeden, aby łańcuch wielowierszowy był bardziej czytelny dla człowieka)

Wyniki są zróżnicowane (jak dopuszcza OP w komentarzu ).

W jaki sposób?

Dzieli na nowe linie, transponuje i łączy ze sobą podsegmenty (do) sześciu, aby uzyskać reprezentacje znaków i odwraca każdą (równoważąc późniejszą konwersję podstawową dla końcowego znaku o długości 25 do wszystkich pozostałych o długości 30). Następnie mapuje '#'i ' 'jeden i zero, odpowiednio wykorzystując fakt, że '#'ma dziwny porządkowa natomiast ' 'ma jeszcze jedną. Czyta każdy tak, jakby to była podstawowa liczba siedem. Skutecznie bierze modulo 81 każdego z nich (w celu uzyskania 27 unikalnych wartości dla 27 możliwych przypadków), a na koniec indeksuje do „magicznego ciągu” z poprawnymi znakami o właściwych indeksach (indeksowanie modulo jest stosowane z ciągiem magicznym o długości 81, aby zapisać 2 bajty).

Oto „magiczny ciąg”, który utworzyłem wraz z (bez rozróżniania wielkości liter) wzorem wyrażenia regularnego, który musiał dopasować (dodałem „ed”, aby uzyskać długość 81):

 ' affectedly Azerbaijan rewaxed naganas jiujitsudankly pase UVB freqHaarlemcoacted'
'^ ..f...e.....z......a..r.w.x...n.g......iuj....d..kly.p.s...vb....qh.....m.o.ct.*'

W związku z tym można go skompresować, wyszukując jedenaście podtekstów jako słów w słowniku Jelly (większość z nich używa domyślnej spacji wiodącej):

' affectedly Azerbaijan rewaxed naganas jiujitsudankly pase UVB freqHaarlemcoacted'
 ^          ^          ^       ^       ^        ^     ^    ^   ^    ^      ^

co skutkuje skompresowanym sznurkiem galaretki, “¥ŒƲVĊ⁾|W£⁼³ƭÇuʋụzḢĖ0ḢẆẠØsĠỌỊ»

Reszta kodu działa w następujący sposób:

ỴZ;6/UOḂḅ7‘ị“...» - Main link: multi-line string, s   e.g. HI as the #s and spaces
Ỵ                 - split on new lines                     ["#   # #####","#   #   #  ","#####   #  ","#   #   #  ","#   # #####"] (each is actually a list)
 Z                - transpose                              ["#####","  #  ","  #  ","  #  ","#####","     ","#   #","#   #","#####","#   #","#   #"] (each is actually a list)
   6/             - six-wise reduce by
  ;               -     concatenation                      ["#####  #    #    #  #####     ","#   ##   #######   ##   #"] (each is actually a list)
     U            - upend (reverse each)                   ["     #####  #    #    #  #####","#   ##   #######   ##   #"] (each is actually a list)
                  -     note: all except the last will be length 30 and like "     ...", which will become [0,0,0,0,0,...], while the last will be length 25 without those five leading zeros.
      O           - cast to ordinals ('#' -> 35, ' '-> 32) [[32,32,...],[35,32,...]]
       Ḃ          - modulo 2 ('#' -> 1, ' ' -> 0)          [000001111100100001000010011111, 1000110001111111000110001] (each is actually a list)
        ḅ7        - convert from base 7 (vectorises)       [223498370543967315553, 191672428080864454753] (these are now integers)
          ‘       - increment                              [223498370543967315554, 191672428080864454754]
                  -  (modulo 81 these would be [68, 41])
           ị      - index into (modulo & 1-indexed):                        
            “...» -     the "magic string" described above ' affectedly Azerbaijan rewaxed naganas jiujitsudankly pase UVB freqHaarlemcoacted'
                                                           "Hi"                                   41^                        68^

14

Python 2 , 405 335 234 182 171 bajtów

lambda s,j=''.join:j(' QPVXU_O__FBLK_JMD_CSYZWIENH_AG___TR'[int(j(`ord(y)%2`for y in j(s.split('\n')[x][i:i+5]for x in range(5))),2)%13836%37]for i in range(0,len(s)/5,6))

Wypróbuj online!


Wreszcie krótszy niż JS


Clever use of the modulus, but I can't help thinking there must be a way to do: [0,2,3,7,...] and ' UBGOTA... split it, and use some sort of mapping. 0:' ',2:'U',3:'V'... looks so long,,, there are so many :'',. (I know you had something similar in the original post, but with very long numbers.
Stewie Griffin

1
@StewieGriffin it is better now
ovs

11

JavaScript (ES6), 204 186 184 182 bytes

Saved 18 bytes thanks to Neil
Saved 2 bytes thanks to ETHproductions
Saved 2 bytes thanks to YairRand

Breakdown:

  • 42-byte lookup table
  • 162 144 142 140 bytes of code
s=>(a=s.split`
`)[0].replace(/.{6}/g,(_,n)=>' H_JM__WDCSORLU___QKG_P_AFT_N_EI_XBV____YZ'[[0,1,2,4].reduce((p,r,i)=>p+='0b'+a[r].substr(n,5).replace(/./g,c=>1^1-c)<<i*6,0)%178%69%43])

Demo


1
You can save a whole bunch of bytes using (a=s.split`\n`)[0].replace(/......?/g, with substr(n,5) and without the join of course.
Neil

I think you can save a byte with c=>0|c>' ', and another with p+='0b'+...
ETHproductions

As mentioned by @Steadybox in the Comment section of the Challenge, taking \n in input is invalid. However, I think you can use template literal with actual newline as input, just like you are doing in the split method.
Arjun

1
@DobbyTheFree-Elf I could indeed use a template literal -- which incidentally would impair the readability because of the leading quote. But adding a constraint on the way the input data is formatted before being passed to the function is out of topic, IMHO (as long as the actual content of the input is valid).
Arnauld

1
@DobbyTheFree-Elf I'm afraid my comment was a bit ambiguous, and I may have slightly misunderstood the question I was answering. Using \n in a string literal at the call site in the code is okay, because the actual string that is passed to the function includes only the newline character, not both \` and n. Passing a string that contains \` and n as separate adjacent characters would not be okay.
Steadybox

9

Bash + ImageMagick + Tesseract, 161 bytes

I wanted to try the approach suggested by @stewie-griffin and went for bash + ImageMagick (to convert a string to an image) and Tesseract (to do the OCR). Here's my code, which works for the 'HELLO WORLD' testcase, but fails the other ones. Maybe some tweaking to the parameters (font, font size, kerning, spacing) helps.

convert -font Courier-Bold -pointsize 8 -interline-spacing -3 -kerning -3 label:"$(</dev/stdin)" -bordercolor White -border 5%x20% png:- | tesseract stdin stdout

Just copy-paste the ascii art into the commandline after running the command. Finish your input by pressing ^d.

Current output for the test cases:

  • HELLO WORLD: HELLO WORLD
  • ASCII: H5511
  • PPCG: PPOG

6

Scala, 184 181 bytes

A magic string + modulo solution based on hashCode :)

(a:String)=>a.split("\n").map(_.grouped(6)map(_.take(5))toArray).transpose.map(l=>"Q__WLUY_XOI_ZN_GEFR_P__JKBMV_S__ __C__D__H_T__A"(Math.abs(l.mkString.hashCode)%106%79%47))mkString

Try online (Scalafiddle)

More readable :

(a:String) => a.split("\n")
                .map(_.grouped(6)map(_.take(5))toArray)
                .transpose
                .map ( l => 
                    "Q__WLUY_XOI_ZN_GEFR_P__JKBMV_S__ __C__D__H_T__A"(
                        Math.abs(l.mkString.hashCode)%106%79%47
                    )
                )mkString

Explanations

  • The initial String (ASCII art) is split into 5 lines (height of ASCII character)
  • Each line is split in 6-characters elements (width of ASCII character + 1 space)
  • Only the first 5 characters are kept (the space at the end is useless)
  • The lines are transposed (each ASCII character is represented as a sequence of 25 characters (5x5), containing either '#' or ' ')
  • Each ASCII character representation (sequence) is converted to String and an absolute hashcode is computed for that String (absolute needed because of next modulus)
  • 3 consecutive modulus (% 106 % 79 % 47) are applied to associate a number ∈ [0; 47[ for each ASCII character (see explanations below)
  • This number is used as an index of the magic string

How to get the magic string ?

First, I represented all letters like this :

case class Letter(letter: Char, ascii: Seq[Char])

Then, I created an alphabet containing ASCII representations of all characters :

Example :

 ### 
#   #  
#####  
#   #  
#   #

becomes

Letter('A', " ### #   #######   ##   #") // 25 characters from top-left to bottom-right

For each letter, an absolute hashcode was computed (all hashcodes are distinct) :

val codes = alphabet.map { case Letter(l, a) => (l, Math.abs(a.mkString.hashCode)) }
// codes: Seq[(Char, Int)] = List(( ,253243360), (A,380997542), (B,1221679148), (C,1573119535), (D,307929190), (E,858088672), (F,857996320), (G,750155628), (H,897290147), (I,1518088099), (J,928547488), (K,1184149391), (L,519601059), (M,741735953), (N,2139154001), (O,1625960980), (P,1307658950), (Q,92382816), (R,1221771494), (S,1689301359), (T,1515228067), (U,1390718627), (V,386730851), (W,733134481), (X,628338619), (Y,23919695), (Z,2081560145))

Then I tried to decrease each code, but always respecting the fact that each code must be unique (the list grouped by the code must have 27 elements, 1 for each letter). So I tried the first 200 modulus :

val mod = (1 to 200).find(modulo => codes.map { case (a,b) => (a, b % modulo) }.groupBy(_._2).size==27).get

I found 106 as the first modulo to be applied :

val codes2 = codes.map { case (l, c) => (l, c%mod) }
val codes = codes2
// codes: Seq[(Char, Int)] = List(( ,32), (A,46), (B,104), (C,35), (D,38), (E,16), (F,96), (G,94), (H,41), (I,89), (J,102), (K,71), (L,83), (M,105), (N,13), (O,56), (P,20), (Q,0), (R,18), (S,29), (T,43), (U,5), (V,27), (W,3), (X,87), (Y,53), (Z,91))

I repeated the previous steps until the smallest modulo. I found :

  • 79
  • 47
  • 44
  • 42

Note : The last modulo I chose (47) is not the smallest here :

  • I found 44, but if I had chosen 44, the magic string would have size 44 (instead of 47) but I would have to write %106%79%47%44 (13 characters instead of %106%79%47 = 10 characters). So in bytes, the code should have had the same size as the one I got
  • There is also 42, but then the code should have had 1 byte more than the one I got

Next, I applied the consecutive modulus (% 79 % 47) to the last codes, to get the definitive codes associated to each letter :

codes: Seq[(Char, Int)] = List(( ,32), (A,46), (B,25), (C,35), (D,38), (E,16), (F,17), (G,15), (H,41), (I,10), (J,23), (K,24), (L,4), (M,26), (N,13), (O,9), (P,20), (Q,0), (R,18), (S,29), (T,43), (U,5), (V,27), (W,3), (X,8), (Y,6), (Z,12))

Finally, to construct the magic string :

val initialMap = (0 until 47).map(i => (i, '_')).toMap
val codesMap = codes.map(i => (i._2, i._1)).toMap

val magicString = (initialMap ++ codesMap).toSeq.sortBy(_._1).map(_._2).mkString
// magicString: String "Q__WLUY_XOI_ZN_GEFR_P__JKBMV_S__ __C__D__H_T__A"

Example : The letter A above is associated to 46 (380997542 % 106 % 79 % 47), and the 46th element of the magic string is A :)

Test cases

// assign function to f
val f = (a:String)=>a.split("\n").map(_.grouped(6)map(_.take(5))toArray).transpose.map(l=>"Q__WLUY_XOI_ZN_GEFR_P__JKBMV_S__ __C__D__H_T__A"(Math.abs(l.mkString.hashCode)%106%79%47))mkString

HELLO WORLD :

val asciiArt = """|#   # ##### #     #      ###        #   #  ###  ####  #     #### 
                  |#   # #     #     #     #   #       #   # #   # #   # #     #   #
                  |##### ####  #     #     #   #       # # # #   # ####  #     #   #
                  |#   # #     #     #     #   #       ## ## #   # #   # #     #   #
                  |#   # ##### ##### #####  ###        #   #  ###  #   # ##### #### """.stripMargin

f(asciiArt)    // HELLO WORLD

ASCII :

val asciiArt = """| ###   ###   ###  ##### #####
                  |#   # #     #   #   #     #  
                  |#####  ###  #       #     #  
                  |#   #     # #   #   #     #  
                  |#   #  ###   ###  ##### #####""".stripMargin

f(asciiArt)    // ASCII

PPCG :

val asciiArt = """|####  ####   ###   ### 
                  |#   # #   # #   # #    
                  |####  ####  #     #  ##
                  |#     #     #   # #   #
                  |#     #      ###   ### """.stripMargin

f(asciiArt)    // PPCG

Edits

  • Saved 3 bytes by removing . before map, toArray and mkString

3

PHP, 294 Bytes

<?$l=" 00000YE00G0000R000A0Q0000C0BW000K00000000000LT00000J00000000MU0000Z0000DI000000V0000000P00H0000ONF000S00X";preg_match_all("#(.{5})\s#s","$_GET[0] ",$t);for($i=0;$i<$c=count($a=$t[1])/5;$i++)$s.=$l[bindec(strtr($a[$i].$a[$i+$c].$a[$i+2*$c].$a[$i+3*$c].$a[$i+4*$c]," #","01"))%106];echo$s;

Try it online!

Expanded

$l=" 00000YE00G0000R000A0Q0000C0BW000K00000000000LT00000J00000000MU0000Z0000DI000000V0000000P00H0000ONF000S00X"; # search string mod 106
preg_match_all("#(.{5})\s#s","$_GET[0] ",$t); # Regex take each group of five chars followed by a whitespace
for($i=0;$i<$c=count($a=$t[1])/5;$i++)
  $s.=$l[bindec(strtr($a[$i].$a[$i+$c].$a[$i+2*$c].$a[$i+3*$c].$a[$i+4*$c]," #","01"))%106]; # join each groups make a binaray make a decimal mod 106  
echo$s; # Output

Converting the Input to an image format

@Stevie Griffin search a solution to get this from an image. I think he want not really the image format I have use.

echo'<svg xmlns="http://www.w3.org/2000/svg" width="100%"><switch><foreignObject x="0" y="0" width="100%" height="300"><body xmlns="http://www.w3.org/1999/xhtml"><pre>'.$_GET[0].'</pre></body></foreignObject></switch></svg>';

SVG can contains HTML parts if then included in a foreignObject. So I put a pre Element in a SVG.

Image Output

<svg xmlns="http://www.w3.org/2000/svg" width="100%"><switch><foreignObject x="0" y="0" width="100%" height="300"><body xmlns="http://www.w3.org/1999/xhtml"><pre>#   # ##### #     #      ###        #   #  ###  ####  #     #### 
#   # #     #     #     #   #       #   # #   # #   # #     #   #
##### ####  #     #     #   #       # # # #   # ####  #     #   #
#   # #     #     #     #   #       ## ## #   # #   # #     #   #
#   # ##### ##### #####  ###        #   #  ###  #   # ##### #### </pre></body></foreignObject></switch></svg>

Solving from Image Changes

SVG is machine readable so after saving the SVG as "i.svg" you need only replace $_GET[0] with preg_replace("#(^.*e>)(.*)(</p.*$)#s","$2",join(file("i.svg"))) in the way with normal input + 55 Bytes


2

Powershell, 152 146 bytes

-join$(for($t=$args-split'
';$c-lt$t[0].Length;$c+=6){$s=0;$t|% s*g $c,5|% t*y|%{$s+=$s+$_}
'_ISRJ_BK_HFQPL_MYNCE _TXDAO_VWUZ__G'[$s%578%174%36]})

Test script:

$f = {

-join$(for($t=$args-split'
';$c-lt$t[0].Length;$c+=6){$s=0;$t|% s*g $c,5|% t*y|%{$s+=$s+$_}
'_ISRJ_BK_HFQPL_MYNCE _TXDAO_VWUZ__G'[$s%578%174%36]})

}

&$f @"
#   # ##### #     #      ###        #   #  ###  ####  #     #### 
#   # #     #     #     #   #       #   # #   # #   # #     #   #
##### ####  #     #     #   #       # # # #   # ####  #     #   #
#   # #     #     #     #   #       ## ## #   # #   # #     #   #
#   # ##### ##### #####  ###        #   #  ###  #   # ##### #### 
"@

&$f @"
 ###   ###   ###  ##### #####
#   # #     #   #   #     #  
#####  ###  #       #     #  
#   #     # #   #   #     #  
#   #  ###   ###  ##### #####
"@

&$f @"
####  ####   ###   ### 
#   # #   # #   # #    
####  ####  #     #  ##
#     #     #   # #   #
#     #      ###   ### 
"@

&$f @"
       ###  ####   ###  ####  ##### #####  ###  #   # ##### ##### #   # #     #   # #   #  ###  ####   ###  ####   ###  ##### #   # #   # #   # #   # #   # #####
      #   # #   # #   # #   # #     #     #     #   #   #     #   #  #  #     ## ## ##  # #   # #   # #   # #   # #       #   #   # #   # #   #  # #   # #     # 
      ##### ####  #     #   # ####  ####  #  ## #####   #     #   ###   #     # # # # # # #   # ####  #   # ####   ###    #   #   #  # #  # # #   #     #     #  
      #   # #   # #   # #   # #     #     #   # #   #   #   # #   #  #  #     #   # #  ## #   # #     #  #  #   #     #   #   #   #  # #  ## ##  # #    #    #   
      #   # ####   ###  ####  ##### #      ###  #   # ##### ###   #   # ##### #   # #   #  ###  #      ## # #   #  ###    #    ###    #   #   # #   #   #   #####
"@

Output:

HELLO WORLD
ASCII
PPCG
 ABCDEFGHIJKLMNOPQRSTUVWXYZ

Note:

  1. $t|% s*g $c,5|% t*y|%{$s+=$s+$_} is shortcut for $t.substring($c,5).toCharArray()|%{$s+=$s+$_}
  2. ("abcd","efgh").substring(1,2) returns the array ("bc","de")
  3. ("bc","de").toCharArray() returns the array ('b','c','d','e')

2

C,  225  209 bytes

Thanks to @ceilingcat for saving 16 bytes!

i,j,k,l,n,m;f(char*s){l=index(s,10)-s+1;for(i=0;i<l/6;++i){for(m=j=0;j<5;m+=n*(exp10(j++)+.1))for(n=k=0;k<5;)n+=(s[i*6+j+k*l]==35)<<k++;for(j=0;"Qi Y$>W);Xa%d^F4K-]7jcMAG="[j++]-32-m%77;);putchar(n?64+j:32);}}

Try it online!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.