Moltiplicazione visiva lunga


28

C'è un buon modo per eseguire una lunga moltiplicazione per due numeri interi senza dover fare altro che contare, che occasionalmente viene condiviso su Internet. Scrivi le cifre di ogni numero come un gruppo di linee inclinate, con i due numeri con un angolo di 90 gradi. Quindi puoi semplicemente contare le intersezioni nelle colonne separate che si presentano. Un diagramma probabilmente lo chiarirà. Ecco un esempio per il calcolo 21 * 32:

inserisci qui la descrizione dell'immagine

Se cerchi Google per "moltiplicazione visiva / grafica" troverai molti altri esempi.

In questa sfida, devi generare questi diagrammi usando l'arte ASCII. Per lo stesso esempio, l'output sarebbe simile al seguente:

   \ /
    X /
 \ / X /
\ X / X
 X X / \ /
/ X X   X /
 / X \ / X
  / \ X / \
     X X
    / X \
     / \

Probabilmente è più facile capire le regole di costruzione per questi da alcuni esempi (vedi sotto), ma qui alcuni dettagli:

  • I segmenti intersecanti sono X, i segmenti non intersecanti delle linee sono /o \.
  • Dovrebbe esserci esattamente un segmento dopo le intersezioni più esterne.
  • Dovrebbe esserci esattamente un segmento tra le intersezioni appartenenti a cifre diverse. Se ci sono cifre zero, queste si tradurranno in segmenti consecutivi /o \.
  • Devi supportare qualsiasi input positivo (almeno fino a un limite ragionevole come 2 16 o 2 32 ) e qualsiasi cifra da 0a 9. Tuttavia, si può presumere che non ci siano né iniziali né finali 0.
  • Non è necessario stampare spazi bianchi iniziali estranei o linee vuote iniziali o finali.
  • È possibile stampare spazi vuoti finali ma non deve superare il riquadro di delimitazione allineato agli assi del diagramma.
  • Se lo si desidera, è possibile stampare una nuova riga finale.
  • Puoi scegliere in quale ordine prendere i due numeri di input. Tuttavia, è necessario supportare numeri arbitrari per entrambi gli orientamenti, quindi non è possibile scegliere qualcosa come "Il numero più grande viene dato per primo".
  • Se stai prendendo input come stringa, puoi usare qualsiasi separatore senza cifre tra i due numeri.

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

Questo è il codice golf, la risposta più breve (in byte) vince.

Esempi

1*1
\ /
 X
/ \

2*61
 \ /
\ X /
 X X /
/ X X /
 / X X /
  / X X /
   / X X
    / X \ /
     / \ X
        X \
       / \

 45*1
         \ /
        \ X
       \ X \
      \ X \
     \ X \
      X \
   \ / \
  \ X
 \ X \
\ X \
 X \
/ \

21001*209
       \ /
        X /
       / X
      / / \
   \ / /   \ /
    X /     X /
 \ / X     / X /
\ X / \   / / X /
 X X   \ / / / X /
/ X \   X / / / X /
 / \ \ / X / / / X /
    \ X / X / / / X /
     X X / X / / / X /
    / X X / X / / / X
     / X X / X / / / \
      / X X / X / /
       / X X / X /
        / X X / X
         / X X / \
          / X X
           / X \
            / \

Una funzione con 2 parametri di stringa o solo una singola stringa e devo dividerla nel mio codice?
edc65,

@ edc65 Due stringhe o anche due parametri interi vanno bene.
Martin Ender,

Risposte:


1

Pyth - 79 byte

Una traduzione della risposta di @ AlexeyBurdin. Probabilmente si può giocare a golf molto di più.

AzHmu++Gm1sH]Zd]Z,_zwK+lzlHJmm\ KK .e.eX@J+kY+-Yklz@" \/x"+byZHzjbmjk:d2_1:J1_2

Accetta input come due numeri, newline separati. Spiegazione in arrivo.

Provalo online qui .


4

pitone, 303

def f(s):
    a,b=s.split('*')
    a,b=map(lambda l:reduce(lambda x,y:x+[1]*int(y)+[0],l,[0]),[reversed(a),b])
    n=sum(map(len,[a,b]))
    l=[[' ']*n for i in xrange(n)]
    for i,x in enumerate(a):
        for j,y in enumerate(b):
            l[i+j][j-i+len(a)]=r' \/x'[x+2*y]
    return '\n'.join(''.join(x[2:-1]) for x in l[1:-2])

Penso che sia abbastanza leggibile dall'uomo.
Verifica:

print '---'
print '\n'.join('"%s"'%x for x in f('21001*209').split('\n'))
print '---'
---
"       \ /            "
"        x /           "
"       / x            "
"      / / \           "
"   \ / /   \ /        "
"    x /     x /       "
" \ / x     / x /      "
"\ x / \   / / x /     "
" x x   \ / / / x /    "
"/ x \   x / / / x /   "
" / \ \ / x / / / x /  "
"    \ x / x / / / x / "
"     x x / x / / / x /"
"    / x x / x / / / x "
"     / x x / x / / / \"
"      / x x / x / /   "
"       / x x / x /    "
"        / x x / x     "
"         / x x / \    "
"          / x x       "
"           / x \      "
"            / \       "
---

1
Solo alcuni campi da golf veloci: reversedè lo stesso di [::-1], puoi mettere il contenuto del ciclo for in una riga per risparmiare sulla rientranza, len(a)+len(b)è più corto di sum(map(len,[a,b])), non usare xrangenel golf, lo spazio in ) forpuò essere rimosso, e dato che sei usando python2, puoi combinare spazi e tabulazioni nel rientro.
Maltysen,

Grazie mille Ciò dà 22 byte. Ma non penso che sarebbe il più breve. Non codifico pyth ma ho visto programmi a 31 byte ... A proposito, 303 è il conteggio quando ogni 4 spazi viene sostituito da una scheda in realtà.
Alexey Burdin,

Qui, sono stato in grado di ottenere 276dal semplice golf sintattico: gist.github.com/Maltysen/e8231c0a9b585e2a4941
Maltysen

Inoltre, ti dispiace se traduco il tuo programma in Pyth e lo pubblico come risposta separata?
Maltysen,

1
Puoi e=enumerateiniziare a giocare a golf 4 caratteri
sagiksp

2

Python 3, 205 byte

L=a,b=[eval("+[0]+[1]*".join("0%s0"%x)[2:])for x in input().split()]
A,B=map(len,L)
for c in range(2,A+B-1):print((" "*abs(c-A)+" ".join(" \/X"[a[i-c]+2*b[i]]for i in range(max(0,c-A),min(c,B))))[1:A+B-2])

Le espressioni sono piuttosto lunghe, quindi penso che ci sia un certo margine di miglioramento, ma comunque ...

Accetta input separato da spazio tramite STDIN, ad es

21 32
   \ /
    X /
 \ / X /
\ X / X  
 X X / \ /
/ X X   X /
 / X \ / X 
  / \ X / \
     X X  
    / X \
     / \

C'è un possibile spazio finale su alcune linee, ma A+B-2garantisce che tutti gli spazi finali siano all'interno del riquadro di delimitazione.


1

C #, 451 byte

void d(string s){var S=s.Split('*');int X=S[1].Select(c=>c-47).Sum(),Y=S[0].Select(c=>c-47).Sum(),L=9*(X+Y),A=1,B=L/3,i,j;var a=Range(0,L).Select(_=>new int[L]).ToArray();foreach(var c in S[1]){for(i=48;i<c;++i){for(j=-1;j<Y;++j)a[B-j][A+j]=1;A++;B++;}A++;B++;}A=1;B=L/3;foreach(var c in S[0]){for(i=48;i<c;++i){for(j=-1;j<X;++j)a[B+j][A+j]|=2;A++;B--;}A++;B--;}Write(Join("\n",a.Select(r=>Concat(r.Select(n=>@" /\X"[n]))).Where(r=>r.Trim().Any())));}

Formattata per la leggibilità, la funzione nel contesto:

using System.Linq;
using static System.Console;
using static System.Linq.Enumerable;
using static System.String;

class VisualMultiply
{
    static void Main(string[] args)
    {
        new VisualMultiply().d("21001*209");

        WriteLine();
    }

    void d(string s)
    {
        var S = s.Split('*');

        int X = S[1].Select(c => c - 47).Sum(), 
            Y = S[0].Select(c => c - 47).Sum(),
            L = 9 * (X + Y),
            A = 1,
            B = L / 3,
            i,
            j;

        var a = Range(0, L).Select(_ => new int[L]).ToArray();

        foreach (var c in S[1])
        {
            for (i = 48; i < c; ++i)
            {
                for (j = -1; j < Y; ++j)
                    a[B - j][A + j] = 1;
                A++;
                B++;
            }
            A++;
            B++;
        }

        A = 1;
        B = L / 3;
        foreach (var c in S[0])
        {
            for (i = 48; i < c; ++i)
            {
                for (j = -1; j < X; ++j)
                    a[B + j][A + j] |= 2;
                A++;
                B--;
            }
            A++;
            B--;
        }

        Write(Join("\n", a.Select(r => Concat(r.Select(n => @" /\X"[n]))).Where(r => r.Trim().Any())));
    }
}

L'OR bit a bit era solo per divertimento, ma anche l'aggiunta avrebbe funzionato.


1

JavaScript ( ES6 ) 271

Sono sicuro che esiste una soluzione che crea l'output riga per riga, armeggiando con matematica e coordinate x, y (x + y == k, xy == k ...). Ma non riesco ancora a inchiodarlo.

Quindi ecco una soluzione che disegna semplicemente le linee una per una.

Esegui lo snippet in Firefox per testare.

F=(a,b)=>( // string parameters
  t=u=0,[for(v of a)t-=~v],[for(v of b)u-=~v],
  r=t+u,o=[...' '.repeat(r*r-r)],
  L=(x,y,n,z,m,c)=>{
    for(i=0;d=n[i++];)
      for(j=0;++x,y+=z,j++<d;)
        for(l=m+1,p=x+y*r-1-r;l--;p+=r-z,o[p-p%r-1]='\n')
          o[p]=o[p]>' '&&o[p]!=c?'X':c
  },
  L(u,0,a,1,u,'/'),
  L(0,u,b,-1,t,'\\'),
  o.join('')
)

// TEST

function test()
{
  O.innerHTML= F(A.value, B.value);
}

test();
<input id=A value=21001> * <input id=B value=209> <button onclick='test()'>-></button>
<pre id=O></pre>


1

VC ++ (289)280

t(char*a){int i,j,k,r,c=1,e,A=0,B=0,*C,G[99],f,u;for(C=&A;c+48|(k=(c=(*(a+=c<1))---48)>0);G[2**(C=!(c+6)?&(B+=A):&(++*C))]=k**C);for(i=0;i<B*B;printf("\n%c"+!!j,32+15*((k=(c<(f=G[(c=i/B)+(j=i%B)+A+2]))*(j<f)*(f>A))+4*(r=(!!e*B>c+(e=G[A+j-c]))*(!!e*c>A-e-2)*(e<A)))+13*k*r),i++);

uso

#include  <stdio.h>
#include  <conio.h>

int t(char*);

int main(void)
{   char a[]="123*45";
    t((char*)a);
    getch();
    return 0;
}

int 
//-------- padded code ------
t(char*a){int i,j,k,r,c=1,e,A=0,B=0,*C,G[99],f,u;memset(G,0,396);for(C=&A;c+48|(k=(c=(*(a+=c<1))---48)>0);G[2**(C=!(c+6)?&(B+=A):&(++*C))]=k**C);for(i=0;i<B*B;printf("\n%c"+!!j,32+15*((k=(c<(f=G[(c=i/B)+(j=i%B)+A+2]))*(j<f)*(f>A))+4*(r=(!!e*B>c+(e=G[A+j-c]))*(!!e*c>A-e-2)*(e<A)))+13*k*r),i++);

//---------------------------
return 0;}

risultati

       \ /
      \ x /
     \ x x /
      x x x /
   \ / x x x
  \ x / x x \ /
   x x / x \ x /
\ / x x / \ x x /
 x / x x   x x x /
/ x / x \ / x x x /
 / x / \ x / x x x
  / x   x x / x x \
   / \ / x x / x \
      x / x x / \
     / x / x x
      / x / x \
       / x / \
        / x
         / \
  • la funzione esegue l'iterazione di un singolo loop e usa alcuni geometricks e ascii insignificanti.

A cosa serve ---48?
LegionMammal978,

@ LegionMammal978 a volte scrivo cose, poi dimentico anche perché l'ho messo lì: D comunque sono impegnato a fare qualcos'altro, quando finisco, mi ricordo male per te; (questo codice va bene nel tuo compilatore)?
Abr001am

@ LegionMammal978 qui, il contenuto dell'array in corrispondenza dell'indice (effettivo) viene sottratto a 48 prima di diminuire, sottraendo 48 per attendere un carattere zero in arrivo, quindi decrementare passo dopo passo in avanti (o indietro come modello ASCII)
Abr001am

48 è la rappresentazione ascii di "0"
Abr001am

1
Vedo ora, funziona come ...)-- - 48)....
LegionMammal978,


0

C (329 b)

int f(char*a){int i,j,r,k,c,h,o,e=15,m=99,A=0,B=0,*C,L[m][m],G[m],*g=G;for(C=&A;(c=*a-48)+48;C=!(c+6)?&B:&(*C+=(*g++=c+1)),a++);for(i=B-1,j=0;j<(r=A+B-1);i--,j++)for(k=0,o=4*!!((*(g-=!*g))---1);k<=*(C=(h=i<0)?&B:&A);k++)L[abs(i)+k][j+k-2*k*h]+=o/(3*h+1)*e;for(i=0;i<r*r;i++)printf("\n%c"+!!(i%r),((h=L[i/r][i%r])>e*4)?120:h+32);}

PROVALO


Sembra che ci siano colonne di spazi dopo ogni personaggio e mancano i segmenti finali non intersecanti alle estremità inferiori. Stai anche usando le cifre in ordine inverso.
Martin Ender,

@ MartinBüttner immagina che qualcuno lo stia facendo sulla luna e tu lo guardi al telescopio, questo è il modo in cui dovresti percepire il diagramma (
scherzando

0

R , 294 byte

d=do.call;r=outer;m=d(r,c(Map(function(y,w)d(c,c(lapply(y%/%10^rev(0:log10(y))%%10,function(z)c(0,rep(w,z))),0)),scan(),1:2),`+`))+1;p=matrix(" ",u<-sum(dim(m)),u);p[d(r,c(lapply(dim(m),seq),function(a,b)nrow(m)-a+b+u*(a+b-2)))]=c(" ","\\","/","X")[m];cat(apply(p,1,paste,collapse=""),sep="\n")

Provalo online!


0

Gelatina , 58 byte

ŒDṙLN‘ƊṚị“\/X ”K€
L‘0xż1xⱮ$F
DÇ€Ḥ2¦+þ/µZJUṖ;J’⁶xⱮżÑṖḊẎḊ$€Y

Provalo online!

Spiegazione

Un programma completo che accetta i due numeri come un elenco di due numeri interi e restituisce una stringa.

Helper link 1: ruota la matrice

ŒD                        | get the diagonals
  ṙ                       | rotate left by
   LN‘Ɗ                   | minus num columns +1
       Ṛ                  | reverse order
        ị“\/X ”           | index into \/X
               K€         | join each with spaces

Helper link 2: genera i modelli di riga e colonna

L‘0x                      | 0 copied (num digits + 1) times
    ż                     | interleaved with
     1xⱮ$                 | 1 copied as specified by the digits
         F                | flattened

Collegamento principale

D                         | convert to decimal digits
 ǀ                       | call above link for each number
   Ḥ2¦                    | double the second one
      +þ/                 | outer product using +
         µ                | start a new monadic chain
          ZJUṖ;J’         | reversed range counting down
                          | the columns, followed by range
                            counting up the rows (without
                            duplicating 0 in the middle)
                   ⁶xⱮ    | that many spaces (to provide indents)
                      ż   | interleaved with
                       Ñ  | rotated matrix
                        ṖḊẎḊ$€ Y | remove blank rows and columns and join with newlines
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.