L'architetto ASCII


15

Non vuoi pagare per il costoso programma di architettura, quindi decidi di fare il tuo. Decidi di utilizzare ASCII per progettare i tuoi edifici. Il tuo programma prenderà una singola stringa formattata in un modo specifico e il programma produrrà l'edificio.

Ingresso

L'input è costituito da una singola riga di caratteri. Si può presumere che contenga solo le lettere a-j, i numeri 1-9, i simboli -e +.

Descrizione dell'uscita

Per ogni lettera a-j, il programma emetterà una linea verticale come segue. Chiameremo questo una colonna.

         .
        ..
       ...
      ****
     *****
    ******
   -------
  --------
 +++++++++
++++++++++
abcdefghij

Ad esempio, l'input abcdefgfedefghgfedcprodurrebbe:

             .
      *     ***
     ***   *****
    ***** *******
   ---------------
  -----------------
 ++++++++++++++++++
+++++++++++++++++++

Una lettera può essere preceduta da un numero intero positivo n, che aggiungerà ncaratteri bianchi sotto la colonna. Chiameremo questo un offset. Ad esempio, usando Sper annotare uno spazio bianco, l'input 3b2b3bprodurrebbe:

+ +
+++
S+S
SSS
SSS

Una lettera può anche essere preceduta da un numero intero negativo-m , che rimuoverà i caratteri inferiori m non bianchi della colonna (non sostituirli con spazi bianchi, rimuoverli completamente). Lo chiameremo una fetta. Ad esempio, l'input -1j-2j-3j-4j-5j-6j-7j-8jprodurrebbe:

.
..
...
*...
**...
***...
-***...
--***...
+--***..

Un offset e una sezione possono essere applicati alla stessa linea, ma l'offset deve essere eseguito per primo. In altre parole, è possibile aggiungere il prefisso alla lettera n-m, dove nè la dimensione dell'offset ed mè la dimensione della sezione. Ad esempio, usando Sper annotare uno spazio bianco, l'input '2-4j' produrrebbe:

.
.
.
*
*
*
S
S

Infine, l' +operatore utilizzato tra due colonne indica che devono essere impilati uno sopra l'altro nella stessa colonna anziché in colonne separate. Ad esempio, l'ingresso `2-4ja 'genera:

.
.
.
*
*
*
S
S+

Considerando che le 2-4j+auscite input :

+
.
.
.
*
*
*
S
S

Ecco un esempio di input:

abiehef+ehfhabc

E l'output risultante:

      *
      -
  .   -
  . . +. .
  * * +* *
  * * ****
  ********
  --------
  --------  -
 +++++++++ ++
+++++++++++++

Sembra una vecchia torre del castello distrutta di qualche tipo.

Ecco un altro input di esempio:

6b5b+a6b1-2d+3-4f1-2d+-2c+2-4f+1-2d+-2c2-2d+1-4g+1-2c+b+-2c+-4e2-7j+-4g+d+-2c+-4f2-7j+-5h+b+-2c+a+-3f2-7j+-7i+-4e+b+b+a+-4f2-7i+a+-7h+-4f+b+b+a+-4f2-7j+-7h+-4f+a+-7h+a+-7i+-4f2-7j+-7i+-6h+a+-7i+b+-4e3-7i+a+-7h+-4e+a+-7h+b+1-7h3-7j+1-4f+-7h+b+-4f+a3-7j+2-4f+a+-4f+b3-2d+-2d+3-4g+b3-2d+-2d+-2c

E l'output risultante:

      ****** +++
     ******+.*++
     ---++.+ ***
    -+-+++..++**
    -+--+++.+++*
    --++++.+..*
      +++++.+**
+++****.******  -
+++*****.**..  --
 +   ***....+..--
      ...+.....--
    --.........--
   ---......
   --

(Doveva essere Mario ma non è andato molto bene ...)

Se la specifica non è ancora chiara, ho un'implementazione non golfata scritta in Python 2.7. Puoi eseguirlo e sperimentare per avere un'idea di come funzionano le specifiche. Puoi anche scegliere di ridere delle mie capacità di programmazione.

Questo è code-golf, quindi vince l'ingresso più breve. Poni domande nei commenti se non è chiaro.


L'impilamento di più di due torri è valido? Vedo "2c + b + -2c" in uno dei tuoi esempi, ma non riesco a capire se è così che li hai impilati.
AndoDaan,

1
Le torri @AndoDaan possono essere impilate all'infinito usando +. Ad esempio, a+a+a+a+agenererebbero cinque segni più uno sopra l'altro.
assenzio


@Howard Huh, hai ragione, questi sono sorprendentemente simili (le uniche aggiunte sono quella di poter tagliare la torre e impilare le torri).
Martin Ender,

@Howard Huh. Non è apparso sulle domande simili che vengono visualizzate quando si digita il titolo. L'implementazione dello spazio bianco è tuttavia leggermente diversa. Contrassegnerò il mio post come duplicato e vedrò cosa pensano le mod.
assenzio

Risposte:


10

Rubino, 223 214 byte

g=$*[0].split(/(?<=[a-j])(?!\+)/).map{|r|r.scan(/(\d*)(-\d+)?([a-j])/).map{|a,b,c|' '*a.to_i+'++--***...'[-b.to_i..c.ord-97]}*''}
puts g.map{|s|s.ljust(g.map(&:size).max).chars.reverse}.transpose.map(&:join).join$/

È stato divertente. :)

Anche se dovrebbe essere abbastanza ovvio, ho scoperto un nuovo modo di fare queste sfide in cui le stringhe sono state costruite da colonne: basta farle in file e trasporre la matrice di caratteri prima di unire tutto.

g=$*[0].split(/(?<=[a-j])(?!\+)/)               # Split into columns.
       .map{|r|                                 # For each column
            r.scan(/(\d*)(-\d+)?([a-j])/)       # Split into components.
             .map{|a,b,c|                       # For each component
                ' '*a.to_i+                     # Prepend spaces if any.
                '++--***...'[-b.to_i..c.ord-97] # Select the appropriate slice of the tower.
            }*''                                # Join all components together.
        }
puts g.map{|s|                                  # For each column
            s.ljust(g.map(&:size).max)          # Pad with spaces on the right such that. 
                                                # all columns are the same height.
            .chars.reverse                      # Turn into character array and reverse.
      }
      .transpose                                # Mirror in the main diagonal.
      .map(&:join)                              # Join lines.
      .join$/                                   # Join columns.

Era provare diversi stili della linea finale ed è venuto fuori con: puts (0..z=g.map(&:size).max-1).map{|i|g.map{|y|(v=y[z-i])?v:?\ }*''}. Ma probabilmente non è così divertente senza la trasposizione.
Vectorized

@bitpwner Grazie, darò un'occhiata e lo proverò più tardi.
Martin Ender,

2

Cobra - 473

Non credo che Cobra vincerà mai uno di questi: /

use System.Text.RegularExpressions
class P
    def main
        r=Regex.matches(Console.readLine,r'(?<=^|[a-j])(([^a-j]*[a-j])+?)(?=[^+]|$)')
        z,l=0String[](r.count)
        for m in r.count,for n in'[r[m]]'.split('+'),l[m]+=' '.repeat(int.parse('0[Regex.match(n,r'(?<!-)\d+')]'))+'++--***...'[int.parse('0[Regex.match(n,r'(?<=-)\d+')]'):' abcdefghij'.indexOf(n[-1:])]
        for y in l,if y.length>z,z=y.length
        for x in-z+1:1
            for y in l,Console.write(if(-x<y.length,y[-x],' '))
            print

Tutto bello e commentato:

EDIT: Ho appena realizzato che sembra sospettosamente simile alla soluzione Ruby. Grandi menti pensano allo stesso modo?

use System.Text.RegularExpressions
class P
    def main
        r=Regex.matches(Console.readLine,r'(?<=^|[a-j])(([^a-j]*[a-j])+?)(?=[^+]|$)')
        # Split into columns
        z,l=0,String[](r.count)
        # Assign the column-array
        for m in r.count
        # Loop through columns
            for n in'[r[m]]'.split('+')
            # Loop through individual letter instructions
            # - within columns
                l[m]+=
                # Add characters to the last column
                    ' '.repeat(int.parse('0[Regex.match(n,r'(?<!-)\d+')]'))+
                    # Any spaces, plus
                    '++--***...'[:' abcdefghij'.indexOf(n[-1:])]
                    # The default column string
                        [int.parse('0[Regex.match(n,r'(?<=-)\d+')]'):]
                        # Sliced to the right length
        for y in l,if y.length>z,z=y.length
        # Determine the maximum length of any column
        for x in-z+1:1
            for y in l
            # Loop through columns so that they rotate to the left
                Console.write(if(-x<y.length,y[-x],' '))
                # Write the character in the current position
            print
            # Insert newlines

2

Lua - 451

a=arg[1]j='++--***...'I=io.write M=string.match U=string.sub T=table.insert n=''y=0 t={}m=0 for i in a:gmatch('[%-%d]*[a-j]%+?')do b=M(i,'-(%d)')b=b or 0 s=M(U(i,1,1),'%d')s=s or 0 n=n..(' '):rep(s)..U(U(j,1,M(U(i,-2),'[a-j]'):byte()-96),1+b,-1)if U(i,-1,-1)~="+"then T(t,n)m=m<#n and #n or m n=""y=y+1 end end T(t,n)n=''for k,v in pairs(t)do n=#v<m and n..v..(' '):rep(m-#v)or n..v end for i=m,1,-1 do for k=0,m*y-1,m do I(U(n,i+k,i+k))end I'\n'end

Niente di speciale. Però, è stato divertente rinominare un carico di funzioni per una volta. Modificherò il codice non salvato più avanti.

Provalo qui. Uscita campione:

SampleOutput


1

PowerShell , 214 212 209 206 200 byte

-3 byte grazie @Veskah

switch -r($args-split'(-?.)'){\+{$c=1}\d{sv('ps'[0-gt$_])$_}[a-j]{if(!$c){$t+=,''}$t[-1]+=' '*$p+-join'++--***...'[-$s..($_[0]-97)];$c=$p=$s=0}}($t|% Le*|sort)[-1]..1|%{-join($t|% *ht $_|% ch*($_-1))}

Provalo online!

Versione meno giocata a golf:

# make table with lines instead columns
switch -r($args-split'(-?.)'){
    \+ {$c=1}
    \d {set-variable ('ps'[0-gt$_]) $_}
    [a-j] {
        if(!$c){$t+=,''}
        $t[-1]+=' '*$p+-join'++--***...'[-$s..($_[0]-97)]
        $c=$p=$s=0
    }
}
# transpose
($t|% Length|sort)[-1]..1|%{
    -join($t|% padRight $_|% chars($_-1))
}

1
Anche il Regex di (-?.)dovrebbe funzionare
Veskah,

eccezionale! Grazie.
mazzy,

0

Python 3, 268 byte

import re
q,t=[(p,' '*int(o or 0)+'++--***...'[-int(s or 0):ord(l)-96])for p,o,s,l in re.findall('(\+?)(\d?)(-\d)?(.)',input())],[]
while q:p,s=q.pop(0);t+=[t.pop()+s if p else s]
t=[*zip(*[[*c.ljust(max(map(len,t)))]for c in t])][::-1]
for l in t:print(*l,sep='')

Per lo più ungolfed:

# import the regex module
import re

# array to store initial input
q = []
# array to store translated output
t = []

# split string from stdin into column groups, like: ('plus or blank', 'offset or blank', 'slice or blank', 'letter')
# ex: 6b1-2d+a would become:
# [('','6','','b'), ('', '1', '-2', 'd'), ('+', '', '', 'a')]
i = re.findall('(\+?)(\d?)(-\d)?(.)',input())

# iterate through the groups returned by the regex
for p,o,s,l in i:
    # create offset string
    # int() cannot parse '', but empty strings are falsey,
    # so (o or 0) is equivalent to 'parse the string as an int, or return 0 if it is empty'
    offset = ' ' * int(o or 0)

    # get the starting point of the slice
    # since the regex returns the minus, it must be negated after converting the string to an int
    # as before, (s or 0) ensures that the slice is converted to an int properly
    start = -int(s or 0)
    # since 'a' is ordinal 97, this ensures that the end position will be 1-9
    end = ord(l) - 96
    # slice the largest possible column string with the calculated start and end positions
    a = '++--***...'[start:end]
    # add the space offset
    a = offset + a
    # add the plus sting and the column string to the array
    q.append( (p, a) )

# while q is not empty
while q:
    # remove the first item from the list and separate it into a plus variable and a column string
    p, s = q.pop(0)

    # if p is not blank, it is a '+'
    # if p is truthy, remove the last item added and add s to it
    # otherwise just return s
    # append the resulting item to the ongoing list
    t += [t.pop()+s if p else s]

temp = []
for c in t:
    # call len() on all items in t, then return the maximum length
    m = max(map(len, t))
    # left justify c by adding spaces to the right, up to m total characters
    c = c.ljust(m)
    # unpack c into a list
    # this is equivalent to list(c), but shorter
    c = [*c]
    # add the list of characters to the array
    temp.append(c)

t = temp

# t is currently a list of rows, and needs to be rotated so that it displays correctly
# input: 'abcdefghij'
# before:
#
# +
# ++
# ++-
# ++--
# ++--*
# ++--**
# ++--***
# ++--***.
# ++--***..
# ++--***...
#
# after:
#
#  ++++++++++
#   +++++++++
#    --------
#     -------
#      ******
#       *****
#        ****
#         ...
#          ..
#           .
# 
t = [*zip(*t)]
# t is currently upside down, reverse the list
t = t[::-1]

# for each line (currently a list of characters)
for l in t:
    # unpack the list into print as arguments, do not add a space between arguments
    print(*l,sep='')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.