Skalieren Sie eine Diamantkachel

27

Jedes reguläre Sechseck kann mit Diamanten gekachelt werden, zum Beispiel so:

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

Wir werden das Obige als Kacheln von Größe betrachten 1(da die Seiten der Diamanten aus einem /oder \jedem bestehen). Die gleiche Kachelgröße 2würde folgendermaßen aussehen:

      ____________ 
     /   /   /\   \  
    /___/___/  \___\ 
   /   /\   \  /\   \  
  /___/  \___\/  \___\ 
 /\   \  /   /\  /   /\  
/  \___\/___/  \/___/  \ 
\  /   /\   \  /   /\  /
 \/___/  \___\/___/  \/ 
  \   \  /   /\   \  /
   \___\/___/  \___\/ 
    \   \   \  /   /
     \___\___\/___/ 

Ihre Aufgabe ist es, eine solche ASCII-Grafikkachel (mit der Größe 1) als Eingabe zusammen mit einer positiven Ganzzahl N(in Dezimal- oder Unärzahl) zu erhalten, die die Größe der gewünschten Ausgabe angibt. Sie sollten dann eine vergrößerte Version derselben Kachel ausgeben.

Beachten Sie, dass das Sechseck beliebig groß und so klein wie 1x1x1 sein kann (mit drei Diamanten).

Weder Eingabe noch Ausgabe dürfen nachgestellte Leerzeichen oder mehr führende Leerzeichen enthalten, als zum Ausrichten der Sechseckform erforderlich sind. Sowohl Eingabe als auch Ausgabe können optional eine einzelne nachgestellte Zeile enthalten (diese Auswahl muss für Eingabe und Ausgabe nicht identisch sein).

Sie können ein Programm oder eine Funktion schreiben, indem Sie eine Eingabe über STDIN (oder die nächstgelegene Alternative), ein Befehlszeilenargument oder ein Funktionsargument vornehmen und das Ergebnis über STDOUT (oder die nächstgelegene Alternative), einen Funktionsrückgabewert oder einen Funktionsparameter (out) ausgeben.

Dies ist Codegolf, daher gewinnt die kürzeste Antwort (in Bytes).

Beispiel Tilings

Hier finden Sie eine Handvoll Eingabefelder, mit denen Sie Ihre Einreichung testen können.

 __
/_/\
\_\/

  ____
 /_/\_\
/\_\/_/\
\/_/\_\/
 \_\/_/

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

    ________
   /_/\_\_\_\
  /\_\/\_\_\_\
 /\/_/\/_/_/\_\
/\/\_\/_/_/\/\_\ 
\/\/_/\_\_\/\/_/
 \/\_\/_/\_\/_/
  \/\_\_\/_/_/
   \/_/_/_/_/

Das folgende Snippet enthält die entsprechenden Ausgaben für Eingaben N = 1bis N = 6.

Martin Ender
quelle
20
Ich sehe, dass Sie sich für Diamanten interessieren, da Sie einen neben Ihrem Benutzernamen haben.
user12205
3
@ace: Sie wissen, was sie sagen: Diamanten sind der beste Freund eines Moderators.
Alex A.
Ich glaube, ich kenne die Antwort, aber ich hoffe, ich liege falsch: Führende Leerzeilen würden als führendes Leerzeichen gelten, das Sie für illegal erklärt haben. Meine anfängliche Lösung hat N-1führende Leerzeilen. :(
Reto Koradi
@RetoKoradi In der Tat keine führenden Zeilenumbrüche. Es tut uns leid.
Martin Ender
1
Ich dachte mir. Hat mich ungefähr 10 Bytes gekostet. Nicht so schlimm, wie es aussah, als ich das Problem zum ersten Mal erkannte.
Reto Koradi

Antworten:

8

CJam, 85 79 76 72 Bytes

li:Tlf*NqN/T,f{ff{"_/"2$#_1<@+*~ST*@t}:+z{S+e`);e~{"_ "/"__"*W%}T2**N}/}

Die Größe sollte in der ersten Zeile stehen. Und der Diamant folgt.

Nicht sehr gut golfen ... Und die Hälfte der Charaktere kam aus den Details.

Erläuterungen (der Vorgängerversion)

li:T            e# Read the size and save to T.
qN/             e# Read and split to lines.
\,fm*           e# Convert each character X to [X 0] [X 1]... [X T(]
{~              e# For each [X I] in each line:
    ST*         e# T spaces.
    \           e# I.
    "_\\"3$#    e# If X is '_, '\ or '/, return Y = 0, 1, -1 respectively.
    _W>@+       e# If it was '_ or '\, increase I by one.
    *(          e# I * Y - 1.
    @t          e# Set the character at that position to X.
}f%
:z:+            e# Make the returned lists from each iteration across T lines.
{S+e`);e~N+}%   e# Boring details to remove trailing spaces and append a newline.
T(>(\s          e# Boring details to extract the first line and only work on others.
{_{"_ "/"__"*W%}2*_@=!}g
                e# Boring details to make underlines expand left and right.
jimmy23013
quelle
10

Python 2, 164

def g(s,n,j=1):
 for W in s.split("\n"):exec"O=p='';d=0\nfor c in W:q=' _'[j*'_'in p+c];e=[n-j,j-1][c=='/'];O+=q*(e+d)+[c,q][c>'^'];p=c;d=n+~e\nprint O;j-=1;"*j;j=n

Ausgabe auf Testfällen.

Also, was ist hier los?

Die Hauptidee ist, dass jedes Zeichen im Original in einen n*nBlock gesprengt wird. Zum Beispiel könnte für n = 4 /werden

   /
  /
 /
/___

Das Originalzeichen wird in jeder Zeile einmal angezeigt, und zu beiden Seiten ist ein Abstand vorhanden. Hier ist es auf der linken Seite, und und _auf der rechten Seite . Es kann nur die unterste Reihe mit aufgefüllt werden '_'. der rest ist immer ' '.

Die Hauptschwierigkeit besteht darin, dass die Polsterung rechts vom kommenden Symbol abhängen kann. Speziell '/ 'hat eine andere Polsterung als '/_', so dass wir eine Vorausschau benötigen würden. Um Leerzeichen zu vermeiden, müssen wir außerdem darauf achten, dass wir am letzten Symbol stehen und nicht rechts auffüllen.

Wir überwinden beide Probleme, indem wir nur links vom aktuellen Zeichen auffüllen. Wenn wir dies tun, führen wir auch das Auffüllen nach rechts vom vorherigen Zeichen unter Verwendung des aktuellen Auffüllsymbols durch. Wir drucken also den vom vorherigen Zeichen geschuldeten rechten Abstand, den linken Abstand vom aktuellen Zeichen und dann den aktuellen Zeichen. Wir speichern auch den Betrag der Auffüllung "Schulden", die der nächste Char bezahlen muss.

Lassen Sie uns nun den Code durchgehen.

def g(s,n,j=1):
    for W in s.split("\n"):
        while j:
            O=p='';d=0
            for c in W:
                q=' _'[j*'_'in p+c]
                e=[n-j,j-1][c=='/']
                O+=q*(e+d)+[c,q][c>'^']
                p=c
                d=n+~e
            print O;j-=1;
        j=n

Die Eingabezeichenfolge ist sund der Skalierungsfaktor ist n. Wir gehen zeilenweise vor und drucken nZeilen für jede Eingabezeile W, wobei die Kopien indiziert werden j=n,n-1,...,2,1. Die erste Zeile wird nur einmal kopiert, was wir erreichen, indem wir sie jauf 1 initialisieren , aber in njede Schleife ändern .

Wir durchlaufen die Eingabezeile und akkumulieren die zu druckende Zeile O. Zunächst ermitteln wir das entsprechende Füllzeichen. Dies qist ein Unterstrich, wenn wir uns in der unteren Zeile befinden und entweder das aktuelle oder das vorherige Zeichen ein Unterstrich und ansonsten ein Leerzeichen ist.

Dann entscheiden wir, wie viel Polster links eingefügt werden soll ( e). Denn /es ist j-1(mit abnehmender Zeilenkopienzahl abnehmend) und das Komplementäre n-jfür \. Wir behandeln andere Charaktere genauso. Obwohl es so _aussieht, als gäbe es eine Reihe von nUnterstrichen, gibt es tatsächlich einen einzelnen Unterstrich, der links und rechts mit Unterstrichen aufgefüllt ist. Dies scheint ineffizient, aber es lässt uns mit arbeitet _und im gleichen Rahmen wie /und \Die Position des „zentralen“ Strich spielt keine Rolle, so dass wir eben damit abfinden müssen und mit \; Durch diese Wahl funktioniert die obere Reihe auch ohne Spezialgehäuse.

Als nächstes ergänzen wir die Ausgabezeichenfolge. Wir haben das Auffüllsymbol qund den aktuellen Auffüllbetrag herausgefunden e, müssen uns aber auch die Auffüllschulden daus dem vorherigen Symbol merken . Also fügen wir hinzu q*(e+d). Dann fügen wir das aktuelle Symbol hinzu c, außer wir müssen Unterstriche in einer nicht-unteren Zeile vermeiden, die wir durch Konvertieren von Unterstrichen in das Füllsymbol beheben.

Schließlich erfassen wir den Auffüllungsbetrag, der das Komplement n+~ddes aktuellen Auffüllungsbetrags darstellt. Wir zeichnen auch das aktuelle Symbol in auf p, damit wir später wissen, ob das vorherige Symbol war _.

xnor
quelle
3

JavaScript ( ES6 ) 274 281 289 338

// GOLFED
F=(b,n)=>{
b=b[R='replace'](/ |_/g,c=>c[T='repeat'](n))[R](/_(?=[\\\/])/g,'_'[T](n))[R](/\/\\/g,`/${'  '[T](n-1)}\\`)
.split('\n');
for(i=l=b.length*n-n+1;--i;)
b[i]=i%n?b[i+1][R](/_/g,' ')[R](/\/ ?/g,' /')[R](/ \\(.)?/g,'\\$1$1')
:' '[T](i>l/2?n-1:0)+b[i/n];
return b.join('\n')}


// UNGOLFED
U=(b,n)=>{
  b=b
  .replace(/ |_/g,c=>c.repeat(n))
  .replace(/_(?=[\/\\])/g,'_'.repeat(n))
  .replace(/\/\\/g,`/${'  '.repeat(n-1)}\\`)
  .split('\n');
  for(i=l=b.length*n-n+1;--i;)
  {
    if(i%n)
     b[i]=b[i+1]
     .replace(/_/g,' ')
     .replace(/\/ ?/g,' /')
     .replace(/ \\/g,'\\ ').replace(/ +$/,'')
     .replace(/ \\(.)?/g,'\\$1$1')
    else {
      b[i]=b[i/n]
      if(i>l/2)b[i]=' '.repeat(n-1)+b[i];
    }
  }
  return b.join('\n')
}

//TEST

test=[
' __\n/_/\\\n\\_\\/',
'  ____\n /_/\\_\\\n/\\_\\/_/\\\n\\/_/\\_\\/\n \\_\\/_/',
'   ______\n  /_/_/\\_\\\n /_/\\_\\/\\_\\\n/\\_\\/_/\\/_/\\\n\\/_/\\_\\/_/\\/\n \\_\\/_/\\_\\/\n  \\_\\_\\/_/',
'    ________\n   /_/\\_\\_\\_\\\n  /\\_\\/\\_\\_\\_\\\n /\\/_/\\/_/_/\\_\\\n/\\/\\_\\/_/_/\\/\\_\\\n\\/\\/_/\\_\\_\\/\\/_/\n \\/\\_\\/_/\\_\\/_/\n  \\/\\_\\_\\/_/_/\n   \\/_/_/_/_/'
]

test.forEach(t=>{
  var row = '<td>'+t+'<td>'
  for(rr=2;rr<5;rr++)
    row += '<td>'+F(t,rr)+'</td>'
  OUT.innerHTML += '<tr>'+row+'</tr>'
})
td {
  font-family: monospace;
  white-space: pre;
}
(better full page)
<table id=OUT></table>

edc65
quelle
3

Python 2, 217 211 195 194 190

b,f,s='\/ '
R=str.replace
def m(g,n,z=1):
 for d in g.split('\n'):
    for i in range(z):a=z+~i;print[i,a][d[-1]>f]*s+R(R(R(R(d,s,s*n),'_','_ '[i<z-1]*(z+n-1)),f+b,f+s*2*i+b),b+f,b+s*2*a+f);z=n

6 Bytes dank Sp3000.

Rufen Sie mmit dem ersten Argument die Raute als Zeichenfolge und dem zweiten Argument die Wiederholungszahl auf.

Dies basiert auf einer 3-stufigen String-Ersetzungssequenz:

  • Ersetzen Sie zuerst Unterstriche durch 2n-1-Leerzeichen oder Unterstriche, je nach Zeile.
  • Zweitens ersetzen Sie /\mit / \, wobei die Anzahl der dazwischen liegenden Leerzeichen zwischen 2 und 2 * (n-1) über den Zeilen liegt.
  • Drittens ersetzen Sie \/durch \ /, wobei die Anzahl der dazwischenliegenden Leerzeichen zwischen 2 * (n-1) und 2 über den Zeilen liegt.

Dann gibt es eine Vielzahl von Mucking, um die führenden Leerzeichen richtig zu machen und die erste Zeile richtig zu machen.

Beachten Sie, dass die letzte Zeile des Programms ein Tabulator sein sollte, nicht 4 Leerzeichen. Markdown unterstützt keine Tabs.

isaacg
quelle
Zwei Golfplätze: (i+(n-i+~i)*(d[-1]>f)) --> [i,n+~i][d[-1]>f]und Sie verwenden nur einen '_', also verschwenden Sie ein Byte, das ihn definiert.
Sp3000,
3

Python, 272 238 228 243 Bytes

Die aktualisierte Version verwendet jetzt eine einzelne Zeichenfolge als Eingabe anstelle einer Zeichenfolgenfolge. Entfernt auch nachfolgende Leerzeichen, die in früheren Versionen vorhanden waren. Leider vergrößern diese Änderungen die Größe.

s,u,f,b=' _/\\'
r=str.replace
def d(t,n,j=1):
 for p in t.split('\n'):
  for k in range(n-j,n):m,v=n+~k,'_ '[k<n-1];print r(r(r(r(r(r(r(r(p,f+u,'(_'),u+b,'_)'),s,s*n),u,v*n),f,s*m+f+s*k),'(',v*m+f+v*k),b,s*k+b+s*m),')',v*k+b+v*m).rstrip();j=n

Version mit Leerzeichen und Anweisungen, die zur besseren Lesbarkeit in kleinere Einheiten unterteilt sind:

s, u, f, b = ' ', '_', '/', '\\'
def d(t, n):
    j = n - 1
    for p in t:
        for k in range(j, n):
            m, v = n - 1 - k, '_ '[k < n - 1]
            q = p[:-1]
            q = q.replace(f + u, '(_')
            q = q.replace(u + b, '_)')
            q = q.replace(s, s * n)
            q = q.replace(u, v * n)
            q = q.replace(f, s * m + f + s * k)
            q = q.replace('(', v * m + f + v * k)
            q = q.replace(b, s * k + b + s * m)
            q = q.replace(')', v * k + b + v * m)
            print q
            j = 0

Der grundlegende Ansatz ist hier:

  1. Schleife über alle Zeilen in der Eingabe.
  2. Durchlaufen Sie für jede Zeile die Ausgabegröße Nund generieren Sie in jeder Schleifeniteration eine Ausgabezeile. Es gibt einen Sonderfall für die erste Zeile, in der nur die letzte Ausgabezeile generiert wird, um zu vermeiden, dass zu Beginn der Ausgabe Leerzeilen generiert werden.
  3. Ersetzen Sie jedes Zeichen in der Zeile durch NZeichen, wobei:
    • Jedes Leerzeichen wird durch NLeerzeichen ersetzt.
    • Jeder Unterstrich wird Nfür die ersten N -1Schleifeniterationen durch Leerzeichen und Nfür die letzten Schleifeniterationen durch Unterstriche ersetzt .
    • Schrägstriche und umgekehrte Schrägstriche werden mit N - 1Leerzeichen oder Unterstrichen aufgefüllt .

Der schwierigste Teil hier ist, dass die Auffüllung für Schrägstriche / Backslashes Leerzeichen oder Unterstriche verwendet, abhängig vom nächsten (für Schrägstriche) oder vorherigen (für Backslashes) Eingabezeichen. Das schien nicht gut zur Strategie der Saitensubstitution zu passen.

Was ich getan habe, um dies zu beheben, ist, dass ich zuerst bestimmte zwei Zeichenkombinationen durch verschiedene Zeichen ersetze, damit ich sie während der tatsächlichen Ersetzung unterschiedlich behandeln kann. Beispielsweise /_wird ersetzt durch (_. Danach (folgt effektiv ein "Schrägstrich gefolgt von einem Unterstrich", der dann entsprechend ersetzt werden kann.

Hauptprogramm zum Testen der Funktion:

import sys
import Golf

n = int(sys.argv[1])
t = ''.join(sys.stdin).rstrip()

Golf.d(t, n)
Reto Koradi
quelle
1
n-1-kistn+~k
rekursiv
Im Interesse der vollständigen Offenlegung: Ich habe gerade festgestellt, dass meine Lösung einige nachgestellte Leerzeichen erzeugt. Da dies in der Ausgabedefinition nicht zulässig ist, werden die Anforderungen nicht erfüllt. Im schlimmsten Fall muss ich .rstrip()9 weitere Zeichen hinzufügen . Ich hoffe, ich kann es besser machen und habe auch einen Weg gefunden, 5 Zeichen auszuschneiden.
Reto Koradi
Es sieht so aus, als ob Ihr Eingabeformat nicht zulässig ist. sys.stdinist kein zulässiger Eingabeparameter - Sie müssen die Zeichenfolge selbst bearbeiten.
isaacg
Nun können Sie verwenden , sys.stdinund , int(sys.argv[1])aber sie sind nicht gonna sie kostenlos von ihnen zu erwarten, in als Variablen übergeben werden (wenn das faire Spiel war, dann könnte man auch Aliase erwarten für rangeund replace` und was Sie sonst noch brauchen , um vordefinieren) .
Martin Ender
@ MartinBüttner Es heißt, dass ich die Eingabe als Funktionsargument nehmen kann. Ist es nicht das, was ich hier mache? Ich würde das Funktionsargument sowieso in eine Liste von Zeichenketten ändern. Wäre das in Ordnung? Es ist nicht sehr unterschiedlich, da beide stdinund eine Liste von Zeichenfolgen Zeichenfolgenfolgen sind.
Reto Koradi
1

Perl, 132

#!perl -p
INIT{$f=pop}s!.!$&x$f!ge;s! $!! while s!\\+\K\\|/(/)! $1!;
for$x(2..m!/!*$f){print y!_! !r;s!\\.?! \\!g;s!./(.)?!/$1$1!g;s!_ !__!g}

Kombinierter STDIN- und ARGV-Eingang. Beispiel:

$ perl ~/hex.pl <~/hex.txt 3
         __________________
        /     /     /\     \
       /     /     /  \     \
      /_____/_____/    \_____\
     /     /\     \    /\     \
    /     /  \     \  /  \     \
   /_____/    \_____\/    \_____\
  /\     \    /     /\    /     /\
 /  \     \  /     /  \  /     /  \
/    \_____\/_____/    \/_____/    \
\    /     /\     \    /     /\    /
 \  /     /  \     \  /     /  \  /
  \/_____/    \_____\/_____/    \/
   \     \    /     /\     \    /
    \     \  /     /  \     \  /
     \_____\/_____/    \_____\/
      \     \     \    /     /
       \     \     \  /     /
        \_____\_____\/_____/
nutki
quelle
1

Ruby 236 237

->i,z{i.split(?\n).map{|l|z.times.map{|y|l.size.times.map{|i|z.times.map{|x|c=l[i]
z<y+2&&(l[i-1..i]=='_\\'||l[i..i+1]=='/_')&&o=?_
(c<?!||(x==y&&c==?\\)||(z==y+1&&c>?^)||(x+y+1==z&&c==?/))&&o=c
o||' '}.join}.join.rstrip}-['']}.join ?\n}

Online-Test: http://ideone.com/e6XakQ

Dies ist der Code vor dem Golfen:

-> diamond, zoom {
  diamond.split(?\n).map do |l|
    zoom.times.map do |y|
      l.size.times.map do |i|
        zoom.times.map do |x|
          out_char = crt_char = l[i]

          out_char = ' '

          # _ has to be continued under / or \
          if zoom == y+1 && l[i-1..i]=='_\\'
            out_char = ?_
          end
          if zoom == y+1 && l[i..i+1]=='/_'
            out_char = ?_
          end

          # logic to "zoom" \, / and _ characters 
          out_char = crt_char if crt_char == ' '
          out_char = crt_char if x==y && crt_char == ?\\  
          out_char = crt_char if zoom==y+1 && crt_char == ?_
          out_char = crt_char if x+y+1==zoom && crt_char == ?/

          out_char
        end.join
      end.join.rstrip
    end - ['']
  end.join ?\n
}
Cristian Lupascu
quelle