Volumi di scatole ASCII


40

introduzione

In questa sfida, ti viene data in input la rappresentazione ASCII della rete (superficie aperta) di un cuboide rettangolare (scatola 3D). Il formato è questo:

....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......

Ogni faccia del cuboide è un rettangolo di #s circondato da +-|caratteri. L'esterno della rete è pieno di .s. La rete avrà sempre lo stesso orientamento: c'è una faccia centrale circondata dalle sue quattro facce vicine, e la controparte della faccia media è al margine destro dell'input. L'input è riempito con .s in una forma rettangolare e non conterrà righe o colonne extra di .s.

L'obiettivo

Il tuo compito è prendere come input un diagramma come sopra e calcolare il volume del cuboide che rappresenta, che è solo il prodotto della sua altezza, larghezza e profondità. È possibile accettare l'input come stringa delimitata da nuova riga o come matrice di stringhe.

La lunghezza di ciascun bordo è la distanza tra i +caratteri alle sue due estremità. Ad esempio, il bordo orizzontale +--+ha lunghezza 3 e il bordo verticale

+
|
|
|
+

ha lunghezza 4. La lunghezza minima di un bordo è 1. L'esempio cuboide sopra ha volume 2 * 3 * 4 = 24.

Regole e punteggio

È possibile scrivere un programma completo o una funzione e vince il conteggio dei byte più basso.

Casi test

.++..
+++++
+++++
.++..
1

...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++....
3

..+-+....
..|#|....
+-+-+-+-+
|#|#|#|#|
|#|#|#|#|
+-+-+-+-+
..|#|....
..+-+....
12

.+---+.....
++---++---+
||###||###|
||###||###|
||###||###|
++---++---+
.+---+.....
16

....++.....
....||.....
....||.....
....||.....
+---++---++
|###||###||
|###||###||
|###||###||
+---++---++
....||.....
....||.....
....||.....
....++.....
16

...+--+......
...|##|......
...|##|......
+--+--+--+--+
|##|##|##|##|
+--+--+--+--+
...|##|......
...|##|......
...+--+......
18

....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......
24

....+-----+..........
....|#####|..........
....|#####|..........
....|#####|..........
+---+-----+---+-----+
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
+---+-----+---+-----+
....|#####|..........
....|#####|..........
....|#####|..........
....+-----+..........
120

13
Mi piace molto questa sfida. Poiché l'input ha una struttura così ridondante, ci sono molte scelte su come recuperare le dimensioni.
xnor

Risposte:


25

Retina , 29 28 byte

T`.p`xy`\G\..+¶
xy

¶\|
$`
y

Provalo online!

Ci sono molti modi per affrontarlo in Retina, a seconda di quale area vuoi moltiplicare con quale parte, quindi non sono sicuro di quanto sia ottimale, ma in realtà è già molto più breve di quanto pensassi.

Al momento ho altre due soluzioni con lo stesso numero di byte che sembrano un po 'più golfabili rispetto all'approccio sopra:

\G\..+¶

¶\|
$'¶
G`\.
T`.|+

¶\||\+¶\.\D+
$'¶
G`\.
T`.|+

Anche se in questi potrei salvare un byte ciascuno se suppongo che l'input termina con un avanzamento riga finale, ma preferirei non fare affidamento su quello.

E un altro, sempre a 28 byte (questo in realtà moltiplica tre lati invece di moltiplicare un'area per lato):

\G\.
x
-(?<=^.+)
$`
¶\|
$`
x

Spiegazione

L'idea principale è di moltiplicare l'area della faccia in alto per la lunghezza del lato verticale che tocca il bordo della lunghezza dell'input.

Userò il seguente input come esempio (ha lunghezze laterali 2, 3 e 4, quindi un'area di 24):

...+---+.......
...|###|.......
...|###|.......
+--+---+--+---+
|##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

Fase 1: traslitterazione

T`.p`xy`\G\..+¶

La regex \G\..+¶corrisponde a una riga che inizia con .ed è immediatamente adiacente alla riga precedente. Quindi questo corrisponde a tutte le linee che contengono la faccia superiore. Il palcoscenico si trasforma .in xe tutti gli altri personaggi (uno qualsiasi |+-#) in y. Questo ci dà il seguente risultato:

xxxyyyyyxxxxxxx
xxxyyyyyxxxxxxx
xxxyyyyyxxxxxxx
+--+---+--+---+
|##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

Questo ha una colonna in più di yquella di cui abbiamo bisogno per rappresentare l'area della faccia superiore. Risolviamo questo problema con la fase successiva.

Fase 2: sostituire

xy

Quindi abbiniamo un yche è preceduto da un x(che è esattamente uno di loro per riga) e li rimuoviamo entrambi dalla stringa. Otteniamo questo:

xxyyyyxxxxxxx
xxyyyyxxxxxxx
xxyyyyxxxxxxx
+--+---+--+---+
|##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

Quindi ora abbiamo l'area della faccia superiore rappresentata dal numero di ys.

Fase 3: sostituire

¶\|
$`

Il nostro obiettivo qui è moltiplicare quest'area Aper la lunghezza del lato mancante, che è il numero |all'inizio di una riga più 1. Tuttavia, in realtà è più facile moltiplicare per un numero n+1perché ne abbiamo già una copia Anella stringa . Se sostituiamo le ncose con A, finiamo con n+1copie di A. Questo rende le cose molto più facili per noi.

Quindi sostituiamo semplicemente qualsiasi |immediatamente dopo un avanzamento di riga con tutto ciò che precede la partita. Questo manipola la stringa abbastanza e la rende un po 'più grande del necessario, ma il numero di ys finisce per essere il risultato che stiamo cercando:

xxyyyyxxxxxxx
xxyyyyxxxxxxx
xxyyyyxxxxxxx
+--+---+--+---+xxyyyyxxxxxxx
xxyyyyxxxxxxx
xxyyyyxxxxxxx
+--+---+--+---+##|###|##|###|
+--+---+--+---+
...|###|.......
...|###|.......
...+---+.......

Fase 4: incontro

y

Non resta che contare il numero di ys, che viene stampato come un numero decimale alla fine.


15

Python 2, 57 byte

lambda l:l[0].find('+')*~l[0].count('-')*~`l`.count("'|")

Una funzione che contiene un elenco di stringhe.

Determina separatamente le 3 dimensioni:

l[0].find('+')
L'indice del primo +nella prima riga.

-~l[0].count('-')
Il numero di -segni nella prima riga.

~`l`.count("'|")
Il numero di righe che iniziano con il |simbolo, tramite la rappresentazione in forma di stringa dell'elenco che precede un simbolo di virgoletta.


62 byte:

def f(l):a=l[0].find('+');print(len(l[0])/2-a)*(len(l)-a+~a)*a

Una funzione che accetta un elenco di stringhe e stampa il risultato.

Trova una dimensione acome indice di +nella prima riga. Le altre due dimensioni ne derivano e la larghezza e l'altezza del rettangolo di input.

Un'alternativa a 63 byte, trovando le dimensioni separatamente:

lambda l:l[0].find('+')*~l[0].count('-')*~zip(*l)[0].count('|')

11

Bash + coreutils, 83, 77 byte

Modifiche:

  • Salvato 6 byte, usando "Here String" e ottimizzando un po 'regexp

golfed

bc<<<`sed -rn '1{s/(.+)[^\.]*\1/(0\1)*(0/
s/\./+1/gp;a)*(-1
}
/^[+|]/a+1
'`\)

spiegato

Trasforma con sed :

....+--+....... => (0+1+1+1+1)*(0+1+1+1 )*(-2 +1
. =>()
. =>()
. =>()
. =>()
+ => +1
| => +1
+ => +1
. =>()
. =>()
. =>()
. =>()

Sbarazzarsi di newline usando backtick, append)

=> (0+1+1+1+1)*(0+1+1+1 )*(-2 +1 +1 +1 +1)

Invia l'espressione risultante a bc

=> 24

Test

./box <<EOF
.++..
+++++
+++++
.++..
EOF

1

./box <<EOF
...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++....
EOF

3

./box <<EOF
....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......
EOF

24

Provalo online! (usa l'espansione aritmetica di bash, invece di bc , poiché quest'ultima non è disponibile)


10

Lumache , 19 byte

AM
=~d^.+\+.+l.+^.2

Provalo online.

L'idea è che iniziamo da qualche parte sul bordo più a destra della rete e poi viaggiamo da qualche parte nella faccia più in basso. La lunghezza del bordo e l'area della faccia vengono moltiplicate per il meccanismo di conteggio di tutti i percorsi corrispondenti.

AM   ,, A -> count all matching paths
     ,, M -> first char matched is the one in the current direction
     ,,      from the starting location, rather than directly on it
=~          ,, check that we are on the right edge of the grid
d ^.+ \+    ,, go down, matching one or more non-'.' characters, then a '+'
.+          ,, go down one or more times
l .+        ,, go left one or more times
^. 2        ,, match two further characters which aren't '.' to the left

4

JavaScript (ES6), 67 91

s=>(a=~-s.search`
`/2-(b=s.indexOf`+`))*b*(s.split`
`.length-1-2*b)

Test

F=
s=>(a=~-s.search`
`/2-(b=s.indexOf`+`))*b*(s.split`
`.length-1-2*b)

out=x=>O.textContent+=x+'\n\n'

;`.++..
+++++
+++++
.++..
1

...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++....
3

..+-+....
..|#|....
+-+-+-+-+
|#|#|#|#|
|#|#|#|#|
+-+-+-+-+
..|#|....
..+-+....
12

.+---+.....
++---++---+
||###||###|
||###||###|
||###||###|
++---++---+
.+---+.....
16

....++.....
....||.....
....||.....
....||.....
+---++---++
|###||###||
|###||###||
|###||###||
+---++---++
....||.....
....||.....
....||.....
....++.....
16

...+--+......
...|##|......
...|##|......
+--+--+--+--+
|##|##|##|##|
+--+--+--+--+
...|##|......
...|##|......
...+--+......
18

....+--+.......
....|##|.......
....|##|.......
....|##|.......
+---+--+---+--+
|###|##|###|##|
+---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......
24

....+-----+..........
....|#####|..........
....|#####|..........
....|#####|..........
+---+-----+---+-----+
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
|###|#####|###|#####|
+---+-----+---+-----+
....|#####|..........
....|#####|..........
....|#####|..........
....+-----+..........
120`
.split('\n\n').forEach(t=>{
  t=t.split('\n')
  k=+t.pop()
  t=t.join('\n')
  v=F(t)
  out(v+' '+k +' '+(v==k?'OK':'KO')+'\n'+t)
})
<pre id=O></pre>


3

Ruby, 44

Funziona su un principio simile ad altre risposte: trova il primo +per trovare la profondità, trova il successivo .dopo +per trovare la larghezza, conta il numero di |alla fine della linea e aggiungi 1 per trovare l'altezza.

->s{(s=~/\+/)*($'=~/\./)*s.split("|
").size}

non golfato nel programma di test

f=->s{(s=~/\+/)*    # index of first match of /\+/ in s
($'=~/\./)*         # $' is a special variable, contains string to right of last match. index of /\./ in $' 
s.split("|
").size}            # split the string at |\n to form an array and count the members

puts f[".++..
+++++
+++++
.++.."]

puts f["...++....
...||....
...||....
+--++--++
+--++--++
...||....
...||....
...++...."]

#etc.

3

05AB1E , 21 byte

Sia Wed Hsia rispettivamente la larghezza e l'altezza dell'input, non la casella. Quindi, La dimensione A, Be Cle seguenti regole:

W = 2(A+C)+1
H = B+2C+1

Gli spettacoli figura che segue quello A, Be Csono, in termini di nomi di bordo:

....AAAA.......
....|##|.......
....|##|.......
....|##|.......
B---+--CCCCC--+
B###|##|###|##|
B---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......

Da qui le formule di cui sopra. Questo programma calcola A, deduce i valori di Be Ced infine calcola il loro prodotto.

S'.ÊO<D¹g<;-(D·|g-()P

S'.Ê                  From each character of the first line, yield 0 if it is '.' or 1 otherwise. The result is stored in an array
    O<D               A = sum(array) - 1
       ¹g<;-(D        C = (W-1)/2 - A
              ·|g-(   B = H-1-2*C
                   )  Yield [A,C,B]
                    P Take the product and implicitly display it

Provalo online!

Versione precedente - Approccio diverso - 26 byte

|vyS'.Ê})¬O<sø¬O<s€O¬Ê1k)P

|                          Take the input as an array of lines (strings)
 vy                        For each line
   S'.Ê                    For each character in the line, yield 0 if it is '.' or 1 otherwise
       }                   End For
        )                  Wrap the results as an array
         ¬O<               A = sum(first_line) - 1
            sø             Transpose the box pattern
              ¬O<          B = sum(first_line) - 1 ; since the pattern is transposed, it corresponds to the first column
                 s€O       Sum every line from the transposed pattern
                    ¬Ê1k   C = index of the first line that has a different sum from the first line
                        )  Yield [A, B, C]
                         P Take the product A*B*C and implicitly display it

2

Befunge 93 , 56 byte

~2%#^_1+
  @.*+<
`"z"~<|:`~0+
5*\`#^_\1>*\~7
%2~\<\+1_^#

Provalo online!

Spiegazione:

Il volume della casella può essere calcolato moltiplicando il numero di .s sulla prima riga prima di qualsiasi altro carattere, per il numero di +e -s sulla prima riga - 1 e il numero di righe che iniziano con un |+ 1.

~2%#^_1+         Uses the ASCII value % 2 of a character to count the .s

%2~\<\+1_^#      IP wraps around to the bottom. Counts the non . chars
                 Works because ("+" % 2) == ("-" % 2) == 1

5*\`#^_\1>*\~7   Multiplies the previous 2 results and cycles through
                 characters until it hits a newline or EOF

`"z"~<|:`~0+     Adds 1 to the 3rd dimension if the following char is a "|"
                 Also checks for EOF; If there is more input, goes back to
                 previous line. Otherwise, goes to the last line

  @.*+<          Adds 1 to the 3rd dimension, multiplies it to the rest,
                 prints the volume, and ends the program

Ho dovuto spostare le linee IP verso l'alto anziché verso il basso per utilizzare la verticale se nella 3a linea. Se l'IP stava scendendo, il verticale se forzerebbe la parte superiore dello stack a 1 quando si colpisce il seguente orizzontale se, inviandolo nella direzione sbagliata.


2

Haskell, 64 56 byte

f(x:r)=sum$fst(span(>'+')x)>>[1|'|':_<-"|":r,'-'<-'-':x]

Provalo online!

Spiegazione

Si prevede che l'input sia un elenco di stringhe per ogni riga, quindi nel fparametro xè presente la prima riga e run elenco delle righe rimanenti.

  1. fst(span(>'+')x)restituisce .-prefix della prima riga come stringa, quindi length(fst(span(>'+')x))è la prima dimensione d1.
  2. Una comprensione di elenco può agire come filtro, ad esempio ['-' | '-' <- x]restituisce una stringa di tutto -nella prima riga, quindi 1 + length['-' | '-' <- x]produce la seconda dimensione d2.
  3. Analogamente si |può contare il numero di nella prima riga, così 1 + length['|' | '|':_ <- r]come la terza dimensione d3.

Le comprensioni di elenco di 2. e 3. possono essere abbreviate 1+sum[1|'-'<-x]e 1+sum[1|'|':_<-r]costruendo un elenco di quelli per ciascuna occorrenza di '-' o '|' e poi prendere la somma. Possiamo aggiungere ulteriormente l'esterno 1+alla comprensione dell'elenco aggiungendo- al xe "|"al rdi cedere sum[1|'-'<-'-':x]e sum[1|'|':_<-"|":r]. Ora possiamo combinare entrambe le comprensioni delle liste mettendo entrambi i predicati nella stessa comprensione: sum[1|'|':_<-"|":r,'-'<-'-':x]convenientemente questo calcola esattamente il prodotto delle due dimensioni perché per le liste Fe Gla seguente comprensione delle liste è il prodotto cartesianoF x G =[(a,b)|a<-F,b<-G] .

Infine, invece di moltiplicare 1. con la combinazione di 2. e 3. possiamo usare l' >>operatore nelle liste: F>>Gripete i G length Ftempi e concatena il risultato. Cosìfst(span(>'+')x)>>[1|'|':_<-"|":r,'-'<-'-':x] ripete l'elenco di d2*d3quelle d1volte, producendo un elenco di d1*d2*d3quelle che vengono quindi riassunte per ottenere il volume.


Puoi prendere l'input come un elenco di stringhe, eliminando la necessità di lines.
Zgarb,

@Zgarb Grazie, questo fa risparmiare qualche byte.
Laikoni,

1

Java 8, 185 129 byte

grazie a Zgarb per -56 byte

golfed:

int g(String[]i){int h=0;for(String k:i){if(k.charAt(0)=='.')h++;else break;}return((i[0].length()-2*h-1)/2)*(i.length-2*h-1)*h;}

ungolfed:

int g(String[] i) {
    int h = 0;
    for (String k : i) {
        if (k.charAt(0) == '.') h++;
        else break;
    }
    return ((i[0].length()-2*h-1)/2)*(i.length-2*h-1)*h;
}

Spiegazione

a*b*h = ((length_of_line-2*h-1)/2)*(number_of_lines-2*h-1)*h

dove ae bsono le dimensioni della base ed hè l'altezza. Puoi trovare hcontando le prime hrighe da dove inizi con a. .


È possibile prendere l'input come una matrice o stringhe, quindi non è necessario suddividerlo manualmente.
Zgarb,

oops grazie, aggiustandolo ...
Bobas_Pett

1

Java, 112 byte

int v(String[]s){int a=s[0].lastIndexOf('+')-s[0].indexOf('+'),b=s[0].length()/2-a;return a*b*(s.length-2*b-1);}

Allargato:

int v(String[] s)
{
  // length of the edge in the first line
  int a = s[0].lastIndexOf('+') - s[0].indexOf('+');
  // length of the second edge
  // int b = s[0].length() - 2 * a - 1; <-- multiplied by 2
  int b = s[0].length()/2 - a; // <-- hack, length is always odd
  // length of the third edge in ()
  // volume
  return a * b * (s.length - 2 * b - 1);
} // end method v

1

Powershell, 68 67 byte

($c="$args"|% i*f +)*($args[0].Length/2-.5-$c)*($args.Count-1-2*$c)

Nota: "$args"|% i*f + è una scorciatoia per"$args".indexOf('+')

Spiegazione

Una buona spiegazione prese dalla risposta dell'Osable :

Sia Wed Hsia rispettivamente la larghezza e l'altezza dell'input, non la casella. Quindi, La dimensione A, Be Cle seguenti regole:

W = 2(A+C)+1
H = B+2C+1

Gli spettacoli figura che segue quello A, Be Csono, in termini di nomi di bordo:

CCCCAAAA.......
....|##|.......
....|##|.......
....|##|.......
B---+--+---+--+
B###|##|###|##|
B---+--+---+--+
....|##|.......
....|##|.......
....|##|.......
....+--+.......

E C è la posizione del primo+ nella prima riga dell'input.

Script di prova:

$f = {

($c="$args"|% i*f +)*($args[0].Length/2-.5-$c)*($args.Count-1-2*$c)

}

@(

,(1, ".++..",
     "+++++",
     "+++++",
     ".++..")

,(3,"...++....",
    "...||....",
    "...||....",
    "+--++--++",
    "+--++--++",
    "...||....",
    "...||....",
    "...++....")

,(12,"..+-+....",
     "..|#|....",
     "+-+-+-+-+",
     "|#|#|#|#|",
     "|#|#|#|#|",
     "+-+-+-+-+",
     "..|#|....",
     "..+-+....")

,(16,".+---+.....",
     "++---++---+",
     "||###||###|",
     "||###||###|",
     "||###||###|",
     "++---++---+",
     ".+---+.....")

,(16,"....++.....",
     "....||.....",
     "....||.....",
     "....||.....",
     "+---++---++",
     "|###||###||",
     "|###||###||",
     "|###||###||",
     "+---++---++",
     "....||.....",
     "....||.....",
     "....||.....",
     "....++.....")

,(18,"...+--+......",
     "...|##|......",
     "...|##|......",
     "+--+--+--+--+",
     "|##|##|##|##|",
     "+--+--+--+--+",
     "...|##|......",
     "...|##|......",
     "...+--+......")


,(24,"....+--+.......",
     "....|##|.......",
     "....|##|.......",
     "....|##|.......",
     "+---+--+---+--+",
     "|###|##|###|##|",
     "+---+--+---+--+",
     "....|##|.......",
     "....|##|.......",
     "....|##|.......",
     "....+--+.......")

,(120,"....+-----+..........",
      "....|#####|..........",
      "....|#####|..........",
      "....|#####|..........",
      "+---+-----+---+-----+",
      "|###|#####|###|#####|",
      "|###|#####|###|#####|",
      "|###|#####|###|#####|",
      "|###|#####|###|#####|",
      "+---+-----+---+-----+",
      "....|#####|..........",
      "....|#####|..........",
      "....|#####|..........",
      "....+-----+..........")

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

Produzione:

True: 1
True: 3
True: 12
True: 16
True: 16
True: 18
True: 24
True: 120

0

Wolfram Language (Mathematica) , 64 byte

(2(x=#@"
")-(y=#@"|")-9)((9-5x+y)^2-9#@".")/54&@*CharacterCounts

Provalo online!

Utilizza il numero di ., |e\n caratteri nell'input per risolvere il volume. Sembra stupido perché c'è una nuova linea al posto di\n .

Se A, Be Csono i lati, allora . = 2C(A+2C), | = 5B+4C-9e \n = B+2C, quindi, possiamo risolvere il volume ABCin termini di questi tre conteggi dei caratteri.

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.