Architekt ASCII

15

Nie chcesz płacić za kosztowny program architektoniczny, więc decydujesz się na własny projekt. Decydujesz się użyć ASCII do projektowania budynków. Twój program pobierze pojedynczy ciąg sformatowany w określony sposób, a program wygeneruje budynek.

Wejście

Dane wejściowe składają się z jednego wiersza znaków. Można założyć, że zawiera on tylko litery a-j, cyfry 1-9oraz symbole -i +.

Opis wyjścia

Dla każdej litery a-jprogram wyświetli pionową linię w następujący sposób. Nazwiemy to kolumną.

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

Na przykład dane wejściowe abcdefgfedefghgfedcwyprowadzałyby:

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

Litera może być poprzedzona dodatnią liczbą całkowitą n, która doda nbiałe znaki poniżej kolumny. Nazwiemy to przesunięciem. Na przykład, używając Sdo zanotowania białych znaków, dane 3b2b3bwyjściowe wyprowadzą:

+ +
+++
S+S
SSS
SSS

Litera może być również poprzedzona ujemną liczbą całkowitą -m, która usunie dolne m znaki spacji w kolumnie (nie zastąpi ich białymi spacjami, całkowicie je usunie). Nazwiemy to plasterkiem. Na przykład dane wejściowe -1j-2j-3j-4j-5j-6j-7j-8jwyprowadzałyby:

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

Przesunięcie i plasterek można zastosować do tej samej linii, ale przesunięcie musi być pierwsze. Innymi słowy, litera może być poprzedzona prefiksem n-m, gdzie njest rozmiarem przesunięcia i mjest rozmiarem wycinka. Na przykład, używając Sdo zanotowania białych znaków, wejście „2-4j” wyświetli:

.
.
.
*
*
*
S
S

Wreszcie +operator użyty między dwiema kolumnami wskazuje, że powinny one być ułożone jedna na drugiej w tej samej kolumnie zamiast w osobnych kolumnach. Na przykład wejście „2-4ja” wyprowadza:

.
.
.
*
*
*
S
S+

Natomiast dane wejściowe 2-4j+a:

+
.
.
.
*
*
*
S
S

Oto przykładowe dane wejściowe:

abiehef+ehfhabc

I wynikowa wydajność:

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

Wygląda jak stara zniszczona wieża zamkowa.

Oto kolejne przykładowe dane wejściowe:

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

I wynikowa wydajność:

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

(Miał być Mario, ale nie okazał się bardzo dobry ...)

Jeśli specyfikacja nadal nie jest jasna, mam implementację bez golfa napisaną w Pythonie 2.7. Możesz go uruchomić i eksperymentować, aby przekonać się, jak działa specyfikacja. Możesz także śmiać się z moich umiejętności programistycznych.

To jest golf golfowy, więc wygrywa najkrótszy wpis. Zadawaj pytania w komentarzach, jeśli są niejasne.

Absynt
źródło
Układanie więcej niż dwóch wież jest ważne? Widzę „2c + b + -2c” w jednym z twoich przykładów, ale nie mogę zrozumieć, czy w ten sposób je ułożyłeś.
AndoDaan,
1
@AndoDaan Towers można ustawiać w nieskończoność za pomocą +. Na przykład a+a+a+a+awyprowadziłoby pięć znaków plus na siebie.
absynt
1
Czy to nie jest duplikat codegolf.stackexchange.com/questions/18967/landscapes ?
Howard,
@ Howard Huh, masz rację, są one zaskakująco podobne (jedyne dodatki to możliwość odcięcia wieży i ułożenia wież).
Martin Ender,
@Howard Huh. Nie pojawił się w podobnych pytaniach, które pojawiają się podczas wpisywania tytułu. Implementacja białych znaków jest nieco inna. Oflaguję mój post jako duplikat i zobaczę, co sądzą mody.
absynt

Odpowiedzi:

10

Ruby, 223 214 bajtów

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$/

To było zabawne. :)

Chociaż powinno to być dość oczywiste, odkryłem nowy sposób wykonywania tych wyzwań, w których ciągi znaków zostały zbudowane z kolumn: po prostu rób je w wierszach i transponuj tablicę znaków przed połączeniem wszystkiego.

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.
Martin Ender
źródło
Było wypróbowanie różnych stylów linii końcowej i wyszedł z: puts (0..z=g.map(&:size).max-1).map{|i|g.map{|y|(v=y[z-i])?v:?\ }*''}. Ale prawdopodobnie nie byłoby tak fajnie bez transpozycji.
Vectorized
@bitpwner Dzięki, przyjrzę się i przetestuję to później.
Martin Ender
2

Kobra - 473

Nie sądzę, że Cobra kiedykolwiek wygra jedną z tych: /

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

Wszystko miłe i skomentowane:

EDYCJA: Właśnie zdałem sobie sprawę, że wygląda podejrzanie podobnie do rozwiązania Ruby. Wielkie umysły myślą podobnie?

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
Obrzydliwe
źródło
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

Nic specjalnego. Fajnie było choć raz zmienić nazwę zestawu funkcji. Wyedytuję później niepoznany kod.

Wypróbuj tutaj. Przykładowe dane wyjściowe:

SampleOutput

AndoDaan
źródło
1

PowerShell , 214 212 209 206 200 bajtów

-3 bajki dzięki @ 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))}

Wypróbuj online!

Wersja mniej golfowa:

# 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))
}
mazzy
źródło
1
Regex od (-?.)powinny działać zbyt
Veskah
niesamowite! dzięki.
mazzy
0

Python 3, 268 bajtów

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='')

W większości nie golfistów:

# 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='')
Triggernometria
źródło