Moltiplica due numeri senza usare alcun numero


30

Vengono fornite come input due stringhe che rappresentano numeri interi positivi nella base 10, come "12345"e "42". Il tuo compito è quello di produrre una stringa contenente il loro prodotto, "518490"in questo caso.

La svolta è che non puoi usare alcun tipo numerico nel tuo codice. No ints, floats, unsigned longs, ecc., Nessun tipo di numero complesso incorporato o numeri interi di precisione arbitraria o qualsiasi cosa lungo quelle linee. Molti non usano letterali di questi tipi, né alcuna funzione, metodo, operatore ecc. Che li restituisce.

È possibile utilizzare stringhe, valori booleani, array o qualsiasi altra cosa che normalmente non verrebbe utilizzata per rappresentare un numero. (Si noti che non è possibile indicizzare in un array né ottenerne la lunghezza senza invocare un tipo numerico.) charSono consentiti, ma non è possibile eseguire alcuna operazione aritmetica o bit a bit su di essi o altrimenti trattarli come nient'altro che un token che rappresenta parte di una stringa. ( charÈ consentito il confronto lessicografico di s.)

Non è possibile aggirare la limitazione. Ciò include (ma non si limita a) l'uso di tipi numerici all'interno di una evalfunzione di tipo, conversioni di tipo implicite in tipi numerici, l'utilizzo di operatori numerici o bit a bit su tipi non numerici che li supportano, l'utilizzo di tipi numerici memorizzati all'interno di tipi di contenitori o la funzione di chiamata o programmi esterni che restituiscono risultati numerici in forma di stringa. (Mi riservo il diritto di aggiungere a questo elenco se compaiono altre soluzioni alternative nelle risposte.) È necessario implementare la moltiplicazione da soli utilizzando solo tipi non numerici.

L'input e l'output possono avvenire con qualsiasi metodo conveniente, purché i dati entrino ed escano dal codice sotto forma di stringa. Puoi presumere che ciascuno dei due argomenti di input contenga solo i caratteri ASCII [0-9]e non inizi con 0. Nemmeno il tuo output dovrebbe avere zero iniziali.

Ancora una cosa: il tuo codice deve gestire correttamente input con una lunghezza massima di almeno 10 caratteri e deve essere eseguito in meno di un minuto su un computer moderno per tutti gli input in quell'intervallo. Prima di pubblicare, controlla che quando vengono forniti input 9999999999e 9999999999, il tuo programma fornisce un output di 99999999980000000001, in meno di un minuto. Questa limitazione esiste specificamente per impedire che le risposte funzionino allocando una matrice di dimensioni a*be quindi ripetendo su di essa, quindi tieni presente che le risposte di quel modulo non saranno idonee a vincere.

Questo è , quindi vince la soluzione valida più breve (in byte).


Possiamo accettare "12345"da STDIN piuttosto che 12345? Oppure possiamo accettare entrambi i numeri come "12345", "42"?
Giustino,

Il mio primo pensiero è stato quello di scrivere una funzione di prendere argomenti stringa di lunghezza med ne restituendo un argomento di lunghezza m*n. Ma poiché le stringhe devono contenere letteralmente la rappresentazione ASCII dei numeri, immagino sia contrario alle regole.
Level River St

1
@xnor in molte lingue potrebbe essere più breve scrivere tutti i casi. Ma in Python l'ho trovato in questo modo:a,b="0123456789x".split('0');c=iter(b).next() if c=='x': c='0'
Nathaniel,

1
o in Python 3,a,b="0123456789x".split(x);c,*d=b if c=='x': c='0'
Nathaniel,

2
@ Nathanield='123456789';I=dict(zip('0'+d,d+'0'))
Giustino

Risposte:


6

Haskell - 180 206 214

r=reverse
f=filter
z=['0'..'9']
a?f|f="1"!a
a?_=a
(a:b)!(c:d)=e:b!d?(e<a)where e=fst$last$zip(f(>=c)z++z)$f(<=a)z
a!c=a++c
a%(b:c)=foldr(!)('0':a%c)$f(<b)z>>[a]
_%b=b
a#b=r$r a%r b

Implementa la moltiplicazione tramite aggiunta ripetuta e tutti i tipi di magia delle cifre vengono gestiti spostando e filtrando l' ['0'..'9']elenco. Definisce un operatore #del tipo String -> String -> String:

*> :set +s
*> "9990123456789"#"9999876543210"
"99900001219316321126352690"
(0.02 secs, 9862288 bytes)

Sembra che abbiamo un nuovo vincitore! (Anche se come prima, non riesco a leggere Haskell di questo grado di raffinatezza - qualcuno può verificare in modo indipendente che soddisfi le specifiche?)
Nathaniel

(Anche ['0' .. '9'] sembra un po 'come trattare implicitamente i caratteri come numeri che possono essere ripetuti - c'è un modo breve per generare quell'elenco dalla stringa "0123456789" invece?)
Nathaniel

@Nathaniel Beh, prima di tutto la stringa "0123456789" è la lista ['0'..'9']. In secondo luogo, in Haskell [a..b] è presente un'enumerazione, i tipi che hanno dichiarato istanze della Enumtabella dei tipi possono essere enumerati in questo modo e la dichiarazione descrive il funzionamento dell'enumerazione. Bool, il tipo booleano ha anche un'istanza e quindi puoi anche farlo [False..True]. Non ci sono quasi numeri coinvolti.
mniip,

14

sed, 339 338 byte

So che questo è vecchio, ma stavo navigando e questo ha suscitato il mio interesse. Abbastanza per registrarsi effettivamente come utente! Immagino di essere stato influenzato da " Vorrei piuttosto vedere una soluzione sed completa - Nathaniel " ...

s/[1-9]/0&/g
s/[5-9]/4&/g
y/8/4/
s/9/4&/g
s/4/22/g
s/[37]/2x/g
s/[26]/xx/g
s/[1-9]/x/g
:o
s/\( .*\)0$/0\1/
/x$/{
x
G
s/ .*/\n/
:a
s/\(.*\)0\(x*\)\n\(.*\)0\(x*\)\n/\1\n\3\n0\2\4/
ta
s/\n//g
:c
s/^x/0x/
s/0xxxxxxxxxx/x0/
tc
x
s/x$//
}
/ 0/bo
g
s/0x/-x/g
s/xx/2/g
y/x/1/
s/22/4/g
s/44/8/g
s/81/9/g
s/42/6/g
s/21/3/g
s/61/7/g
s/41/5/g
s/-//g

Questo script sed prevede due numeri decimali come input, separati da uno spazio

test:

time test 518490 = $(./40297.sed <<<)"12345 42" || echo fail
time test 99999999980000000001 = $(./40297.sed <<<"9999999999 9999999999") || echo fail
time test 1522605027922533360535618378132637429718068114961380688657908494580122963258952897654000350692006139 = $(./40297.sed <<<"37975227936943673922808872755445627854565536638199 40094690950920881030683735292761468389214899724061") || echo fail
time test 1230186684530117755130494958384962720772853569595334792197322452151726400507263657518745202199786469389956474942774063845925192557326303453731548268507917026122142913461670429214311602221240479274737794080665351419597459856902143413 = $(./40297.sed <<<"33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917") || echo fail

Potresti riconoscere gli ultimi due come RSA-100 (50 x 50 cifre) e RSA-768 (116 x 116 cifre).

Utilizzando GNU sed su un non molto moderno (Intel Core 2 dell'era del 2007), l'ultimo di questi richiede più di un minuto, ma arriva più velocemente su un processore più recente:

  • Q6600:> 1 minuto
  • i7-3770: 26 secondi
  • i7-6700: 22 secondi

Il moltiplicativo a 10 cifre indicato nella domanda prende ben meno di un secondo su uno di questi (nonostante sia pieno di nove patologici).

Credo che sia standard sed, senza estensioni. POSIX garantisce uno spazio di trattenimento di soli 8192 byte, il che ci limita a moltiplicare i numeri di 400x400 cifre, ma le implementazioni possono fornire di più. GNU sed è limitato solo dalla memoria disponibile, quindi potrebbe gestire qualcosa di molto più grande, se sei disposto ad aspettare.

E sono sicuro di aver rispettato le regole: è quasi un dato di fatto in una lingua che non ha numeri. :-)

Spiegazione

Uso un ibrido unario / decimale, convertendo i numeri decimali in una sequenza unaria:

 42 => _xxxx_xx

In decimale unario, l'aggiunta è semplice. Passiamo dalla cifra meno significativa alla cifra più significativa, concatenando le x:

   X=965                   Y=106                                 SUM
   _xxxxxxxxx_xxxxxx_xxxxx _x__xxxxxx
   _xxxxxxxxx_xxxxxx       _x_                          _xxxxxxxxxxx
   _xxxxxxxxx              _x                    _xxxxxx_xxxxxxxxxxx
                                      _xxxxxxxxxx_xxxxxx_xxxxxxxxxxx

Quindi rimuoviamo gli spazi bianchi e ci occupiamo di carry convertendo 10 x consecutive in una delle unità successive:

 _xxxxxxxxxx_xxxxxx_xxxxxxxxxxx       10.6.11
 _xxxxxxxxxx_xxxxxxx_x                10.7.1
 _x__xxxxxxx_x                        1.0.7.1 

Una volta aggiunta, la moltiplicazione è possibile. Moltiplichiamo x * y considerando l'ultima cifra di y. Aggiungi x all'accumulatore tante volte, quindi passa alla cifra successiva e sposta di x di un decimale a sinistra. Ripeti fino a quando y è zero.

Codice espanso

#!/bin/sed -f

# Convert to unary decimal.  We save two or three bytes of code by
# reusing 0 as the digit separator.
s/[1-9]/0&/g
s/[5-9]/4&/g
y/8/4/
s/9/4&/g
s/4/22/g
s/[37]/2x/g
s/[26]/xx/g
s/[1-9]/x/g

# until y==0

:one

# y ends in zero => x *= 10 and y /= 10
s/\( .*\)0$/0\1/

# while y%10, acc += x, y -= 1
/x$/{
x
G
s/ .*/\n/
# Add x
:add
s/\(.*\)0\(x*\)\n\(.*\)0\(x*\)\n/\1\n\3\n0\2\4/
tadd
s/\n//g
:carry
s/^x/0x/
s/0xxxxxxxxxx/x0/
tcarry

# repeat for each unit of y
x
s/x$//
}

# y?
/ 0/bone


# convert hold space to decimal
g
s/0x/-x/g
s/xx/2/g
y/x/1/
s/22/4/g
s/44/8/g
s/81/9/g
s/42/6/g
s/21/3/g
s/61/7/g
s/41/5/g
s/-//g

1
Risposta molto soddisfacente, grazie!
Nathaniel,

9

sed, 379 byte

Il merito di questa brillante risposta va a @LuigiTiburzi su Unix e Linux.SE: https://unix.stackexchange.com/a/37213/34061 . Mi è capitato di imbattermi in questo pochi giorni fa:

s/[0-9]/<&/g
s/0//g
s/1/|/g
s/2/||/g
s/3/|||/g
s/4/||||/g
s/5/|||||/g
s/6/||||||/g
s/7/|||||||/g
s/8/||||||||/g
s/9/|||||||||/g
:t
s/|</<||||||||||/g
tt
s/<//g
s/.*\*$/0/
s/^\*.*/0/
s/*|/*/
:m
s/\(|*\)\*|/\1<\1*/
tm
s/*//g
s/<//g
:b
s/||||||||||/</g
s/<\([0-9]*\)$/<0\1/
s/|||||||||/9/
s/||||||||/8/
s/|||||||/7/
s/||||||/6/
s/|||||/5/
s/||||/4/
s/|||/3/
s/||/2/
s/|/1/
s/</|/g
tb

Ampia spiegazione

  • Separare ogni cifra. Così 12*3diventa<1<2*<3
  • Converti ogni cifra in quel numero di |caratteri. Così <1<2*<3diventa<|<||*<|||
  • Sostituire ripetutamente |<con <||||||||||per spostare i decimali più alti tutti verso la posizione delle unità. Così <|<||*<|||diventa<||||||||||||*<|||
  • Rimuovi <. Così <||||||||||||*<|||diventa||||||||||||*|||
  • Rimuovere 1 |dall'RHS di *. Così ||||||||||||*|||diventa||||||||||||*||
  • Sostituire ripetutamente ciascuno |sull'RHS con tutto |sull'LHS. Ciò ha l'effetto di moltiplicare il numero LHS e RHS di |dare il numero di prodotto di | Così ||||||||||||*||diventa||||||||||||||||||||||||||||||||||||*
  • Rimuovi *. Così ||||||||||||||||||||||||||||||||||||*diventa||||||||||||||||||||||||||||||||||||
  • converti il ​​numero di |ritorno in decimale dall'inverso dei primi passi. Così ||||||||||||||||||||||||||||||||||||diventa 36.

Produzione:

$ echo "04*3
4*3
40*3
42*32
150*20
1*3
3*1
0*3
3*0" | sed -f mult.sed
12
12
120
1344
3000
3
3
0
0
$

Sfortunatamente fallisce miseramente il tempo richiesto - 200*1000impiega 41 secondi sulla mia macchina virtuale Ubuntu e il tempo di esecuzione sembra empiricamente salire con il quadrato del prodotto finale.


1
Questo è quasi algoritmicamente equivalente alla mia risposta JS cancellata ad eccezione della conversione in parte numerica.
Ottimizzatore

@Optimizer concordato. La differenza è che il tuo usa length()che restituisce un numero. Questo usa una sostituzione puramente regex senza tipi numerici. Penso che la tua risposta sia potenzialmente vincente anche se se riesci a rimuovere il length()- forse potresti fare una sostituzione regex simile invece?
Trauma digitale

1
Molto bello, ma la limitazione di un minuto ha lo scopo specifico di prevenire le soluzioni che funzionano contando fino alla risposta. Mi piacerebbe piuttosto vedere una soluzione sed completa però.
Nathaniel,

1
Ho una risposta che funziona su grandi numeri (ad es. Più grandi dello spazio degli indirizzi del sistema).
Toby Speight,

@TobySpeight sì, molto bene. Penso che dovrei aver già votato il tuo un po 'di tempo fa :)
Digital Trauma

9

Python - 312 286 273

D={}
e=t=""
N=[e]
for c in"0123456789":D[c]=t;D[t]=c;t+="I";N+=N
B=lambda s:[D[c]for c in reversed(s)]
Y=B(input())+N
for a in B(input())+N:
 for c in a:
    s=[];o=e
    for a,b in zip(N,Y):i=a+b+o;o=t<=i and"I"or e;s+=i.replace(t,e),;N=s
 Y=[e]+Y
print e.join(B(N)).lstrip("0")

Se sono consentiti (molti) zero iniziali, gli ultimi 12 caratteri non sono necessari.

Questo essenzialmente esegue manualmente la moltiplicazione standard. Le cifre sono rappresentate come stringhe di Is ripetute (come numeri romani primitivi). I numeri sono rappresentati come elenchi di cifre in ordine inverso. L'aggiunta di singole cifre viene eseguita cocatenando le stringhe e rimuovendo dieci Ise necessario.

Ecco una versione non golfata:

N = [""] # zero object: list with a lot of empty strings
D = {}   # dictionary for conversion from and to digits
i = ""   # iterates over digits
for c in "0123456789":
    D[c] = i  # map digit to Roman digit
    D[i] = c  # and vice versa
    i += "I"  # increments Roman digit
    N += N    # add leading zeros to zero

ten = "IIIIIIIIII" # Roman digit ten

# Conversion function
B = lambda s: [D[c] for c in reversed(s)]

def Add(x,y):
    Sum = []
    carryover = ""
    for a,b in zip(x,y):
        increment = a+b+carryover
        carryover = "I" if ten in increment else ""
        increment = increment.replace(ten,"") # take increment modulo ten
        Sum += [increment]
    return Sum

def M(x,y):
    Sum = N[:] # Initiate Sum as zero
    X = B(x)+N # Convert and add leading zeros
    Y = B(y)+N
    for a in X:
        for c in a:
            Sum = Add(Sum,p+Y)
        Y = [""] + Y # multiply Y by 10
    return "".join(B(Sum)).lstrip("0") # Convert back and to string, remove leading zeros.

M(input(),input())

1
Cos'è questa stregoneria! Come funziona! Wow. Inoltre, ecco un altro golf che potresti fare: def A(x,y):\n S=[];o=""-> def A(x,y,S=[],o=""):. Inoltre, sfortunatamente, ["","1"][t in i]non è permesso; sta usando un bool per indicizzare, trattandolo come un numero. Penso che t in i and"1"or""dovrebbe funzionare, però.
Giustino,

@Quincunx: la definizione Scome argomento con un valore predefinito non avrebbe funzionato, poiché sarebbe sempre lo stesso elenco anche per chiamate diverse della funzione e quindi non reimpostato su []. Avevi ragione ["","1"][t in i], l'ho risolto. Ho anche aggiunto una spiegazione.
Wrzlprmft,

Questo è piuttosto sorprendente. Ottiene il segno di spunta verde per ora. (Ho modificato la domanda per chiarire che gli zero iniziali nell'output non sono consentiti - scusate!)
Nathaniel,

7

Rubino: 752 698

Questo è solo per ottenere una risposta là fuori, appena fatto per curiosità. Modificato: ora golf un po '.

$F='0123456789'
$G="#{$F}abcdefghij"
def x(a,b);p(a=~/[13579]$/?b:"",a==""?"":x(Hash[*%w(b0 5 b1 6 b2 7 b3 8 b4 9)].to_a.inject(a.tr($F,'0011223344').chars.zip(a.tr($F,'ababababab').chars).flatten.join("")){|n,q|k,v=q;n.gsub(k,v)}.gsub(/[ab]/,'').sub(/^0*/,''),p(b,b)));end
def p(a,b);j,k=["0#{a}","0#{b}"].map{|c|c.gsub(/./,'0')};c="#{k}#{a}".chars.zip("#{j}#{b}".chars).drop_while{|z|z==%w(0 0)}.map{|m|$G.sub(/#{m.map{|n|"122333444455555666666777777788888888999999999".chars.select{|c|c==n}}.flatten.map{|c|'.'}.join("")}/,"").chars.first}.flatten.join("");d=nil;
while c!=d
 d=c;c="0#{d}".gsub(/[0-9][a-j]/) {|m| m.tr($G,"123456789a#{$F}")}.sub(/^0/,'')
end;c;end
puts x(ARGV.shift,ARGV.shift)

Uso: ho avuto questo in un file chiamato peasant.rb:

$ time ruby peasant.rb 9999999999 9999999999
99999999980000000001

real    0m0.129s
user    0m0.096s
sys 0m0.027s

Spiegazione: è una moltiplicazione contadina, quindi ho dimezzato e raddoppiato ripetutamente. Dimezzare si ottiene dimezzando le cifre e contrassegnando i resti in questo modo: 1234 -> 0b1a1b2a; quindi trova e sostituisci su b: 06a17a; poi ripulendo -> 617.

L'aggiunta viene eseguita in questo modo ... prima di tutto, riempio entrambe le stringhe della stessa lunghezza e faccio coppie dalle cifre. Quindi aggiungo le cifre costruendo una stringa che ha la lunghezza di ogni cifra e concatenandola; Rimuovo una stringa di quella lunghezza dall'inizio di "0123456789abcdefghij" e quindi mantengo il primo carattere. Ad esempio, "9" + "9" -> "i". NB Evito di utilizzare effettivamente le funzioni di lunghezza qui per evitare del tutto i tipi di numeri; la rimozione del prefisso viene invece eseguita con regexp.

Quindi ora ho una stringa contenente un mix di cifre e lettere. Le lettere rappresentano numeri con una cifra di trasporto; Anticipo 0 al numero, quindi sostituisco ripetutamente i modelli di lettere e lettere con il risultato del carry fino al completamento dell'aggiunta.


1
Risposta molto intelligente, esattamente il genere di cose che speravo di vedere!
Nathaniel,

1
Spero davvero che qualcuno ne pubblichi uno con i numeri della Chiesa!
bazzargh,

Sarebbe bello, anche se non sono sicuro che funzionerebbe con il requisito di efficienza - penso che la conversione tra stringhe e numeri di Church implicherebbe effettivamente il conteggio fino a 99999999980000000001.
Nathaniel

7

Brainfuck (1328 byte)

Considerazioni all'inizio:

  • Non sono sicuro che brainfuck sia una risposta valida a queste domande poiché non sono sicuro se consideri i valori delle celle come "tipi numerici" o meno. Non credo, dato che bf non conosce i tipi, ma questa è la mia opinione, per favore correggimi se sbaglio.
  • È necessaria un'implementazione a supporto di valori (quasi) illimitati.
  • Potrebbe essere troppo lento, in base all'implementazione.

Ho testato il programma solo con il mio interprete, lo puoi trovare qui .

L'input deve essere entrambi i numeri separati da un singolo spazio ASCII.

golfed:

,>++++++[<----->-]<--[>,>++++++[<----->-]<--]>>>+<<<<[>>++++[<<---->>-]<<[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<,[>,]>>>+<<<<[>>+++++++[<<------->>-]<<+[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<<<<<[>>[>+>+<<-]>>[<<+>>-]<<<<-]>>[-]>[<+>-]<[>>+>+<<<-]>>>[<<<+>>>-]<[[-]<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<-]>[<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<->>[-]]+>-]<-]<<+>]<[>>+<<-]>>[<<<[>+>+<<-]>>[<<+>>-]>-]<<[<<->>-]<[-]<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[>>]+[<<]>[>[>>]<+<[<<]>-]<<<<<<<<<<[>>+>+<<<-]>>>[<<<+>>>-]+[<+>-]<<<[-]>>[<<+>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+<<-]>>[<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<<->>>[-]]+>-]<-]<<<+>>]<[-]<<<<[-]>>>[<<<+>>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[<+>-]<]<[>+>+<<-]>>[<<+>>-]<[>+<[-]]+>[<[-]<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[[-]>>>>>>>>[>>]<[<[<<]<<<<<+>>>>>>>[>>]<-]<-<<[<<]<<<<<>++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<.[-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]+[<->-]<<<<<[-]>>>>[<<<<+>>>>-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]<[<+>-]<]<[-]]<[>>++++++[<++++++++>-]<.[-]<[-]]<[-]<[-]>>>>>>>>>>>>[>[-]>]<<[-<<]<<<<<<<<<<<<<<<<<[-]<[-]

Ungolfed:

,
>++++++[<----->-]<--
[                                           # read input until space
    >,
    >++++++[<----->-]<--                    # decrease cell by 32 to check if it's a space
]
>>>+<<<<                                    # set multiplier to 1

[

    >>++++[<<---->>-]<<                     # decrease by 16 to get cell value of number

    [>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]        # multiply value by multiplier
    >>>>>[<<<<<+>>>>>-]                     # copy value back
    <[>++++++++++<-]>[<<+>>-]               # multiply multiplier by 10
    <<<<<                                   # go back to number

    [->+<]>[-<+>]                           # add value to next cell and move sum to previous cell

    <<                                      # go to next number
]

>>>>[-]<                                    # delete old multiplier

,[>,]                                       # read second number until end of input
>>>+<<<<                                    # set new multiplier

[

    >>+++++++[<<------->>-]<<+              # decrease by 48 to get cell value of number

    [>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]        # multiply value by multiplier
    >>>>>[<<<<<+>>>>>-]                     # copy value back
    <[>++++++++++<-]>[<<+>>-]               # multiply multiplier by 10
    <<<<<                                   # go back to number

    [->+<]>[-<+>]                           # add value to next cell and move sum to previous cell

    <<                                      # go to next number
]

>>>>[-]<<<<<                                # delete multiplier

[>>[>+>+<<-]>>[<<+>>-]<<<<-]>>[-]>          # multiply both values

# magical algorithm for printing cell value as number taken from Cedric Mamo's code from a previous question
[<+>-]<[>>+>+<<<-]>>>[<<<+>>>-]<[[-]<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<-]>[<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<->>[-]]+>-]<-]<<+>]<[>>+<<-]>>[<<<[>+>+<<-]>>[<<+>>-]>-]<<[<<->>-]<[-]<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[>>]+[<<]>[>[>>]<+<[<<]>-]<<<<<<<<<<[>>+>+<<<-]>>>[<<<+>>>-]+[<+>-]<<<[-]>>[<<+>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+<<-]>>[<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<<->>>[-]]+>-]<-]<<<+>>]<[-]<<<<[-]>>>[<<<+>>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[<+>-]<]<[>+>+<<-]>>[<<+>>-]<[>+<[-]]+>[<[-]<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[[-]>>>>>>>>[>>]<[<[<<]<<<<<+>>>>>>>[>>]<-]<-<<[<<]<<<<<>++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<.[-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]+[<->-]<<<<<[-]>>>>[<<<<+>>>>-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]<[<+>-]<]<[-]]<[>>++++++[<++++++++>-]<.[-]<[-]]<[-]<[-]>>>>>>>>>>>>[>[-]>]<<[-<<]<<<<<<<<<<<<<<<<<[-]<[-]

Ho preso il codice per l'output del valore da questa risposta , grazie all'autore per quello!

Il programma potrebbe non essere valido, ma in entrambi i casi ho voluto condividerlo con te ^^

Aggiornamento: ora puoi provarlo (solo per piccole moltiplicazioni) qui, grazie alla risposta di @ Sp3000 a questo concorso e ai nuovi frammenti di stack di SE!

var NUM_CELLS = 30000;var ITERS_PER_SEC = 100000;var TIMEOUT_MILLISECS = 5000;function clear_output(){document.getElementById("output").value="";document.getElementById("stderr").innerHTML=""}function stop(){running=false;document.getElementById("run").disabled=false;document.getElementById("stop").disabled=true;document.getElementById("clear").disabled=false;document.getElementById("wrap").disabled=false;document.getElementById("timeout").disabled=false;document.getElementById("eof").disabled=false}function interrupt(){error(ERROR_INTERRUPT)}function error(e){document.getElementById("stderr").innerHTML=e;stop()}function run(){clear_output();document.getElementById("run").disabled=true;document.getElementById("stop").disabled=false;document.getElementById("clear").disabled=true;document.getElementById("wrap").disabled=true;document.getElementById("timeout").disabled=true;document.getElementById("eof").disabled=true;code=document.getElementById("code").value;input=document.getElementById("input").value;wrap=document.getElementById("wrap").value;timeout=document.getElementById("timeout").checked;eof=document.getElementById("eof").value;loop_stack=[];loop_map={};for(var e=0;e<code.length;++e){if(code[e]=="["){loop_stack.push(e)}else if(code[e]=="]"){if(loop_stack.length==0){error(ERROR_BRACKET);return}else{var t=loop_stack.pop();loop_map[t]=e;loop_map[e]=t}}}if(loop_stack.length>0){error(ERROR_BRACKET);return}running=true;start_time=Date.now();code_ptr=0;input_ptr=0;cell_ptr=Math.floor(NUM_CELLS/2);cells={};iterations=0;bf_iter(1)}function bf_iter(e){if(code_ptr>=code.length||!running){stop();return}var t=Date.now();for(var n=0;n<e;++n){if(cells[cell_ptr]==undefined){cells[cell_ptr]=0}switch(code[code_ptr]){case"+":if(wrap=="8"&&cells[cell_ptr]==255||wrap=="16"&&cells[cell_ptr]==65535||wrap=="32"&&cells[cell_ptr]==2147483647){cells[cell_ptr]=0}else{cells[cell_ptr]++}break;case"-":if(cells[cell_ptr]==0){if(wrap=="8"){cells[cell_ptr]=255}if(wrap=="16"){cells[cell_ptr]=65535}if(wrap=="32"){cells[cell_ptr]=2147483647}}else{cells[cell_ptr]--}break;case"<":cell_ptr--;break;case">":cell_ptr++;break;case".":document.getElementById("output").value+=String.fromCharCode(cells[cell_ptr]);break;case",":if(input_ptr>=input.length){if(eof!="nochange"){cells[cell_ptr]=parseInt(eof)}}else{cells[cell_ptr]=input.charCodeAt(input_ptr);input_ptr++}break;case"[":if(cells[cell_ptr]==0){code_ptr=loop_map[code_ptr]}break;case"]":if(cells[cell_ptr]!=0){code_ptr=loop_map[code_ptr]}break}code_ptr++;iterations++;if(timeout&&Date.now()-start_time>TIMEOUT_MILLISECS){error(ERROR_TIMEOUT);return}}setTimeout(function(){bf_iter(ITERS_PER_SEC*(Date.now()-t)/1e3)},0)}var ERROR_BRACKET="Mismatched brackets";var ERROR_TIMEOUT="Timeout";var ERROR_INTERRUPT="Interrupted by user";var code,input,wrap,timeout,eof,loop_stack,loop_map;var running,start_time,code_ptr,input_ptr,cell_ptr,cells,iterations
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;"> <div style="float:left; width:50%;"> Code: <br> <textarea id="code" rows="4" style="overflow:scroll;overflow-x:hidden;width:90%;">,>++++++[<----->-]<--[>,>++++++[<----->-]<--]>>>+<<<<[>>++++[<<---->>-]<<[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<,[>,]>>>+<<<<[>>+++++++[<<------->>-]<<+[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<<<<<[>>[>+>+<<-]>>[<<+>>-]<<<<-]>>[-]>[<+>-]<[>>+>+<<<-]>>>[<<<+>>>-]<[[-]<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<-]>[<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<->>[-]]+>-]<-]<<+>]<[>>+<<-]>>[<<<[>+>+<<-]>>[<<+>>-]>-]<<[<<->>-]<[-]<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[>>]+[<<]>[>[>>]<+<[<<]>-]<<<<<<<<<<[>>+>+<<<-]>>>[<<<+>>>-]+[<+>-]<<<[-]>>[<<+>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+<<-]>>[<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<<->>>[-]]+>-]<-]<<<+>>]<[-]<<<<[-]>>>[<<<+>>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[<+>-]<]<[>+>+<<-]>>[<<+>>-]<[>+<[-]]+>[<[-]<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[[-]>>>>>>>>[>>]<[<[<<]<<<<<+>>>>>>>[>>]<-]<-<<[<<]<<<<<>++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<.[-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]+[<->-]<<<<<[-]>>>>[<<<<+>>>>-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]<[<+>-]<]<[-]]<[>>++++++[<++++++++>-]<.[-]<[-]]<[-]<[-]>>>>>>>>>>>>[>[-]>]<<[-<<]<<<<<<<<<<<<<<<<<[-]<[-]</textarea> <br>Input: <br> <textarea id="input" rows="2" style="overflow:scroll;overflow-x:hidden;width:90%;">7 6</textarea> <p> Wrap: <select id="wrap"> <option value="8">8-bit</option> <option value="16">16-bit</option> <option value="32" selected="selected">32-bit</option> </select> &nbsp; Timeout: <input id="timeout" type="checkbox"></input>&nbsp; EOF: <select id="eof"> <option value="nochange">Same</option> <option value="0" selected="selected">0</option> <option value="-1">-1</option> </select> </p> </div> <div style="float:left; width:50%;"> Output: <br> <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea> <p> <input id="run" type="button" value="Run" onclick="run()"></input> <input id="stop" type="button" value="Stop" onclick="interrupt()" disabled="true"></input> <input id="clear" type="button" value="Clear" onclick="clear_output()"></input> &nbsp; <span id="stderr" style="color:red"></span></p></div></div>


Non so nemmeno se sia valido! Immagino che tutto sia un numero in Brainfuck, o niente lo è.
Nathaniel,

Mi piace questa risposta. Ultimamente mi sono preso gioco di me. in qualche modo fa luce sul fatto che a livello di macchina, tutto è semplicemente un segno. Difficile dire se questo segue davvero le regole o no.
Polpo,

6

Python, 394 349 340 caratteri

D='0123456789'
R=reversed
U=lambda x:[R for y in D if y<x]
T=U(':')
def A(a,b,r='',c=[]):
 for x,y in map(None,R(a),R(b)):
    d=U(x)+U(y)+c;t=T;c=[R]
    if d<T:t=c=[]
    r=min(k for k in D if U(k)+t>=d)+r
 if c:r='1'+r
 return r
a,b=input()
m=''
while b:
 if list(b).pop()in'13579':m=A(m,a)
 b=list(A(b,A(b,A(b,A(b,b)))));b.pop();a=A(a,a)
print m

Esegui come:

echo '"9999999999","9999999999"' | ./mulstr.py

Richiede 50 millisecondi.

Utilizza la moltiplicazione contadina russa . Quando si aggiungono le cifre, le convertiamo in unarie ('5' => [R, R, R, R, R]), concateniamo gli elenchi, quindi riconvertiamo. Uconverte in unario, usando Rcome cifra unaria. Calcoliamo b/=2come b=b*5/10.


Un paio di golf: def A(a,b):\n r='';c=[]-> def A(a,b,r='',c=[]):, allo stesso modo per def M. Potresti essere in grado di passare for z in D:d.pop()\n c=['X']a [d.pop()for z in D];c=['X'], nel qual caso potresti anche comprimerlo sul precedente if. Inoltre, può if list(b).pop()in'13579'essere if b[:].pop()in'13579'?
Giustino,

@Quincunx: grazie. L'ultimo non funzionerà perché nella prima iterazione bè una stringa, non un elenco.
Keith Randall,

È possibile saltare Me scrivere un programma completo; a,b=input() È permesso.
Giustino,

1
b * 5/10 è un bel trucco.
bazzargh,

Ho appena imbattuto reduce, che consente di nicen A(b,A(b,A(b,A(b,b))))a reduce(A,[b,b,b,b,b]). Purtroppo, questo non influisce sul conteggio dei personaggi.
Wrzlprmft,

5

JavaScript (E6) 375395 411 449

Modifica golf
Modifica bug risolto: mancava la cancellazione di una bandiera di trasporto

Può essere fatto con la sola manipolazione di simboli in circa 0 volte.
In questa versione è possibile utilizzare qualsiasi carattere anziché le cifre, purché il simbolo sia in ordine crescente.

Note: utilizzo di stringhe, hashmap con chiave stringa, matrici utilizzate come elenco. Nessuna indicizzazione, le matrici vengono attraversate usando 'map' o ruotate usando push & shift.
Tutti i "+" sono concatenazioni di stringhe.

M=(x,y,S=a=>a.shift()||z,R=a=>[...a].reverse(),e=R('9876543210'),d=[...e])=>
  R(y)[T='map'](b=>
     R(x)[T](a=>(
       u=R[e[a+=b]+v],
       v=R[S[a]+(u<v?'1':z)],
       p[P](t=R[S(o)+u]),
       t<u?v=R[v+'1']:v
     ),o=p,p=[])
    +(v>z&&p[P](v),x+=v=z),
    d[T](a=>d[T](b=>e[P='push'](R[a+b]=S(e)))+e[P](S(e))),  
    d[T](a=>d[T](b=>e[d[T](c=>v=c<a?(u=R[u+b])<b?R[v+'1']:v:v,v=u=z='0'),S[a+b]=v,a+b]=u)),
    p=[v=z]
  )&&R(p).join(o)

Meno golfato (forse aggiungerò una spiegazione domani)

M=(x,y)=>(
  R=a=>[...a].reverse(),
  // Addition table s 
  s={},
  e=[...'9012345678'],
  [for(a of(d='0123456789'))for(b of(e.push(e.shift()),d))e.push(s[a+b]=c=e.shift())],
  // Multiplication table m,n
  m={},n={},
  [for(a of d)for(b of d)(
     [for(c of(z=u=v='0',d))
     c<a&&(t=s[u+b],t<u?v=s[v+'1']:v,u=t)
     ],m[a+b]=u,n[a+b]=v
  )],
  x=R(x),v=z,o=[],p=[],
  [for(b of R(y))(
     [for(a of x)(
       u=s[m[a+b]+v],v=s[n[a+b]+(u<v?'1':z)],
       p.push(t=s[(o.shift()||z)+u]),
       t<u?v=s[v+'1']:v
     )],
     v>z?p.push(v):o,o=p,p=[],x.unshift(v=z)
  )],
  R(o).join('')
)

Test nella console FireFox / FireBug

t0=-new Date
r=M('9999999999','9999999999')
t1=-new Date
console.log("Result",r, "time ms", t0-t1)

Produzione

Result 99999999980000000001 time ms 14

Forse c'è un piccolo bug - l'output del 9999999999caso dovrebbe essere 99999999980000000001, non99999999980000000081
Nathaniel

:( andando a controllare
edc65,

Se stai utilizzando le tabelle di moltiplicazione, come stai aggirando il fatto che la somma non è consentita?
COTO

1
La somma è consentita utilizzando una tabella hash (s nel codice). Ex. s ['34 '] ->' 7 '. Solo simboli, non numeri. Potrebbe essere s ['cd'] -> 'g'
edc65,

5

Haskell, 231 byte

Questo definisce un operatore # che moltiplica due rappresentazioni di stringa di numeri naturali. Funziona definendo un'operazione elementare di incremento / decremento sulle stringhe, quindi la utilizza per creare addizioni e moltiplicazioni. Un po 'di magia in più dà alcune accelerazioni esponenziali che rendono tutto possibile ..

r=reverse
n="9876543210"
t=True
c&(x:y)|c==x=head y|t=c&y
m%[]="1";m%(c:s)|c==last m=head m:m%s|t=c&m:s
[]!y=y;x![]=x;(x:a)!('0':b)=x:a!b;x!y=(r n%x)!(n%y)
"0"?_="0";x?('0':y)|all(=='0')y="0"|t=('0':x)?y;x?y=x?(n%y)!x
x#y=r$r x?r y

Questo approccio è abbastanza veloce che anche su un laptop 2008 nel REPL ghci non ottimizzato, il test case richiede solo una frazione di secondo:

λ> :set +s
λ> let test = replicate 10 '9'
(0.00 secs, 0 bytes)
λ> test
"9999999999"
(0.00 secs, 1069784 bytes)
λ> test # test
"99999999980000000001"
(0.06 secs, 13451288 bytes)

Ecco un controllo che tutti i prodotti a due cifre sono corretti:

λ> and [ show (x * y) == (show x # show y) | x <- [0..100], y <- [0..100] ]
True

Sembra che abbiamo un nuovo leader! (Non riesco a leggere Haskell però - qualcuno può confermare indipendentemente che si adatta alle specifiche?)
Nathaniel

1
Sì, è perfettamente hashell cromulento, si adatta alle specifiche e funziona come pubblicizzato. Buon lavoro!
bazzargh,

4

Bash + ImageMagick: 52

convert -size ${a}x${b} xc:red txt:-|grep -v g|wc -l

Si aspetta che l'input sia nelle variabili shell ae b. Non è particolarmente intelligente o efficiente, ma fa il lavoro. Probabilmente è già stato fatto prima.

Si noti che xdenota le dimensioni dell'immagine; non è un operatore aritmetico in questo contesto.

Non l'ho provato, ma sono disposto ad assumere che per input non estremi, si completerà in meno di un minuto. Posso provarlo domani.

Nel caso ci siano affari divertenti con le versioni di ImageMagick, questa è quella che sto usando: ImageMagick 6.7.7-10


Bel tentativo, ma sono certo che non funzionerà in meno di un minuto (o addirittura su qualsiasi macchina esistente) per input 9999999999e 9999999999.
Nathaniel,

4
Questo funziona anche: dd if=/dev/zero bs=$a count=$b 2>&-|wc -c.
jimmy23013,

1
9999999999x9999999999Un'immagine in formato 8bit occuperà tutto lo spazio del disco rigido che attualmente esiste sulla Terra. Certo, un png sarebbe molto più piccolo, se puoi crearlo senza prima creare l'immagine grezza. (Anche se sospetto fortemente che avresti problemi di overflow di interi con un'immagine di quelle dimensioni.) Tuttavia, un tale metodo quasi sicuramente fallirebbe nella scappatoia delle cose chiamanti che restituiscono risultati numerici come stringhe.
Nathaniel,

1
È possibile salvare 2 byte utilizzando $binvece di ${b}.
nyuszika7h

1
Inoltre, puoi salvare 5 byte usando grep -vc ginvece di grep -v g|wc -l.
nyuszika7h

2

Python 2 (proof of concept)

Questa soluzione funziona utilizzando solo stringhe ed elenchi e un po 'di regex. Credo che si adatti perfettamente alle specifiche, tranne per il fatto che 9999999999x9999999999in un minuto non potrà farlo . Anche se dato abbastanza tempo funzionerebbe. Può moltiplicare i numeri di 4 cifre abbastanza rapidamente.

Dal momento che non è tecnicamente valido, non mi sono ancora preso la briga di giocarci completamente. Lo farò se le regole cambieranno.

import re
D='123456789'
D=dict(zip('0'+D,D+'0'))

def toRlist(s):
    if s:t,h=re.match(r'(\d*)(\d)',s).groups();return[h,toRlist(t)]
    return''

def increment(r):
    if not r:return['1','']
    h,t=r
    return[D[h],increment(t)if h=='9'else t]

def toString(r):
    if not r:return''
    h,t=r
    return h+toString(t)

def listify(r,L):
    if not r:return
    h,t=r
    if h=='1':L.append('')
    if h=='2':L.extend(['',''])
    if h=='3':L.extend(['','',''])
    if h=='4':L.extend(['','','',''])
    if h=='5':L.extend(['','','','',''])
    if h=='6':L.extend(['','','','','',''])
    if h=='7':L.extend(['','','','','','',''])
    if h=='8':L.extend(['','','','','','','',''])
    if h=='9':L.extend(['','','','','','','','',''])
    listify(t,L);listify(t,L);listify(t,L);listify(t,L);listify(t,L)
    listify(t,L);listify(t,L);listify(t,L);listify(t,L);listify(t,L)

def add(r1,r2):
    L=[];listify(r2,L)
    for _ in L:r1=increment(r1)
    return r1

def multiply(a,b):
    total=''
    r=toRlist(a)
    L=[];listify(toRlist(b),L)
    for _ in L:total=r if total=='' else add(total,r)
    return''.join(reversed(toString(total)))

Esempi:

multiply('12','5') #returns the string 60

multiply('1869','1243') #returns the string 2323167

1
+1 perché soddisfa le specifiche (a parte il requisito di efficienza) per quanto posso dire
Nathaniel

2

Python 2 (555)

Normalmente non risponderei alla mia sfida così rapidamente (o per niente), ma volevo dimostrare che poteva essere fatto. (Fortunatamente alcune altre risposte l'hanno fatto prima di questo, ma non ho potuto fare a meno di voler finirlo.) C'è un po 'più di golf che si potrebbe fare, ma penso che sia ragionevole. Gestisce il 9999999999x9999999999caso in meno di 0,03 secondi sulla mia macchina.

d="123456789";I=dict(zip('0'+d,d+'0'))
def r(x):return reversed(x)
def s(x):return''.join(x)
def i(x):
    try:
        h=I[x.next()]
        if h!='0':h+=s(x)
        else:h+=i(x)
        return h
    except:return'1'
def b(x,y):
    for c in'0'+d:
        if c==y:break
        x=iter(i(x))
    return x
def a(x,y):
    z=''
    for c in y:
        x=b(x,c)
        try:z+=x.next()
        except:z+='0'
    return z+s(x)
def n(x,y):
    z='0'
    for c in'0'+d:
        if c==y:break
        z=a(iter(z),x)
    return z
def o(x,y):
    x=s(x)
    l='';z=''
    for c in y:
        z=a(iter(z),l+s(n(x,c)))
        l+='0'
    return z
def m(x,y):
    return s(r(o(r(x),r(y))))

Esempio di utilizzo: m("12345","42")

Funziona facendo una lunga moltiplicazione usando manipolazioni di stringhe. A volte le variabili sono stringhe e talvolta sono iteratori su stringhe, il che rende possibile ottenere il primo elemento senza usare un valore intero letterale. Tutto è memorizzato con le cifre invertite, in modo che il primo elemento sia la cifra meno significativa.

Ecco una spiegazione funzione per funzione:

  • re ssono funzioni di contabilità. ( rè solo un alias per reversed, che crea un iteratore inverso e sconverte gli iteratori in stringhe.)

  • iincrementa il numero in una stringa di 1, inclusi casi come 39+1=40e 99+1=100.

  • baggiunge xe y, ma ydeve essere solo una cifra. Funziona aumentando i x ytempi.

  • aaggiunge due numeri insieme che possono avere più cifre, chiamando bciascuna cifra in y.

  • nsi moltiplica xe y, ma ydeve essere solo una cifra. Funziona aggiungendo xa se stesso i ytempi.

  • osi moltiplica xe y, dove entrambi gli argomenti possono avere più cifre. Utilizza la classica moltiplicazione lunga

  • mconverte semplicemente i suoi input di stringa in iteratori inversi e li passa a o, quindi inverte il risultato e lo converte in una stringa.


Coppia golf: def a(x,y):-> def a(x,y,z=''):e rimuovi la riga successiva; trucchi simili per altre funzioni, in def o(x,y):, cambiano x=s(x)in x=s(x);l='';z='', in quello per loop, allo stesso modo rimuovi newline + paces; invece usa ;. Inoltre, penso che if h!='0':h+=s(x)\nelse:h+=i(x)possa essere semplicemente h+=h!='0'and i(x)or s(x); forse anche h+=(h!='0'and i or s)(x); altrimenti, cambia semplicemente in if'0'!=h. Anche cose come def r(x):return reversed(x)->r=reversed
Giustino

Inoltre, ho dimenticato di dire per s, m: s=lambda x:''.join(x), m=lambda x,y:s(r(o(r(x),r(y))))anziché l'intero dichiarazione di funzione. Con solo le cose che so funzionare, questo porta il conteggio dei byte a 521.
Giustino

Oh, e ancora uno: per i tuoi forloop: for c in'0'+d:\nif c==y:break\nz=a(iter(z),x)-> for c in'0'+d:\nif c!=y:z=a(iter(z),x), anche se questo potrebbe cambiare significativamente la velocità del tuo programma.
Giustino,

@Quincunx grazie! Posso vedere anche altri miglioramenti questa mattina. (Principalmente annidando i loop invece di definire le funzioni.) Apporterò questi cambiamenti se compaiono alcune risposte più competitive, il che sembra probabile - attualmente mi metterebbero in testa, il che sembra un po 'ingiusto poiché era la mia domanda e io' dovevo pensarci più a lungo.
Nathaniel,

2

JavaScript: 3710 3604 byte

  • Utilizzo delle tabelle di ricerca delle stringhe con moltiplicazione di 1 cifra e aggiunta con carry.
  • La moltiplicazione viene effettuata per cifra x cifra anziché cifra x linea.

Golf:

var M={
'00':'0','01':'0','02':'0','03':'0','04':'0','05':'0','06':'0','07':'0','08':'0','09':'0',
'10':'0','11':'1','12':'2','13':'3','14':'4','15':'5','16':'6','17':'7','18':'8','19':'9',
'20':'0','21':'2','22':'4','23':'6','24':'8','25':'10','26':'12','27':'14','28':'16','29':'18',
'30':'0','31':'3','32':'6','33':'9','34':'12','35':'15','36':'28','37':'21','38':'24','39':'27',
'40':'0','41':'4','42':'8','43':'12','44':'16','45':'20','46':'24','47':'28','48':'32','49':'36',
'50':'0','51':'5','52':'10','53':'15','54':'20','55':'25','56':'30','57':'35','58':'40','59':'45',
'60':'0','61':'6','62':'12','63':'18','64':'24','65':'30','66':'36','67':'42','68':'48','69':'54',
'70':'0','71':'7','72':'14','73':'21','74':'28','75':'35','76':'42','77':'49','78':'56','79':'63',
'80':'0','81':'8','82':'16','83':'24','84':'32','85':'40','86':'48','87':'56','88':'64','89':'72',
'90':'0','91':'9','92':'18','93':'27','94':'36','95':'45','96':'54','97':'63','98':'72','99':'81'
};
var A={
'000':'0','001':'1','002':'2','003':'3','004':'4','005':'5','006':'6','007':'7','008':'8','009':'9',
'010':'1','011':'2','012':'3','013':'4','014':'5','015':'6','016':'7','017':'8','018':'9','019':'10',
'020':'2','021':'3','022':'4','023':'5','024':'6','025':'7','026':'8','027':'9','028':'10','029':'11',
'030':'3','031':'4','032':'5','033':'6','034':'7','035':'8','036':'9','037':'10','038':'11','039':'12',
'040':'4','041':'5','042':'6','043':'7','044':'8','045':'9','046':'10','047':'11','048':'12','049':'13',
'050':'5','051':'6','052':'7','053':'8','054':'9','055':'10','056':'11','057':'12','058':'13','059':'14',
'060':'6','061':'7','062':'8','063':'9','064':'10','065':'11','066':'12','067':'13','068':'14','069':'15',
'070':'7','071':'8','072':'9','073':'10','074':'11','075':'12','076':'13','077':'14','078':'15','079':'16',
'080':'8','081':'9','082':'10','083':'11','084':'12','085':'13','086':'14','087':'15','088':'16','089':'17',
'090':'9','091':'10','092':'11','093':'12','094':'13','095':'14','096':'15','097':'16','098':'17','099':'18',
'100':'1','101':'2','102':'3','103':'4','104':'5','105':'6','106':'7','107':'8','108':'9','109':'10',
'110':'2','111':'3','112':'4','113':'5','114':'6','115':'7','116':'8','117':'9','118':'10','119':'11',
'120':'3','121':'4','122':'5','123':'6','124':'7','125':'8','126':'9','127':'10','128':'11','129':'12',
'130':'4','131':'5','132':'6','133':'7','134':'8','135':'9','136':'10','137':'11','138':'12','139':'13',
'140':'5','141':'6','142':'7','143':'8','144':'9','145':'10','146':'11','147':'12','148':'13','149':'14',
'150':'6','151':'7','152':'8','153':'9','154':'10','155':'11','156':'12','157':'13','158':'14','159':'15',
'160':'7','161':'8','162':'9','163':'10','164':'11','165':'12','166':'13','167':'14','168':'15','169':'16',
'170':'8','171':'9','172':'10','173':'11','174':'12','175':'13','176':'14','177':'15','178':'16','179':'17',
'180':'9','181':'10','182':'11','183':'12','184':'13','185':'14','186':'15','187':'16','188':'17','189':'18',
'190':'10','191':'11','192':'12','193':'13','194':'14','195':'15','196':'16','197':'17','198':'18','199':'19'
} 
Array.prototype.e=function(){return(''+this)==='';}
String.prototype.s=function(){return this.split('').reverse();}
function B(a,b,c) {
var r='',s='';
a=a.s();
b=b.s();
while (!a.e()||!b.e()||c!=='0') {
x=a.e()?'0':a.shift();
y=b.e()?'0':b.shift();
s=A[c+x+y];
s=s.s();
r=s.shift()+r;
c=s.e()?'0':'1';
}
return r;
}
function m(a,b) {
var s='0',m='';
b.split('').reverse().forEach(function(e){
var z=m;
a.split('').reverse().forEach(function(f){s=B(s,M[e+f]+z,'0');z+='0';});
m+='0';
});
return s;
}

Non rigato con prove:

var mul = {
'00':'0','01':'0','02':'0','03':'0','04':'0','05':'0','06':'0','07':'0','08':'0','09':'0',
'10':'0','11':'1','12':'2','13':'3','14':'4','15':'5','16':'6','17':'7','18':'8','19':'9',
'20':'0','21':'2','22':'4','23':'6','24':'8','25':'10','26':'12','27':'14','28':'16','29':'18',
'30':'0','31':'3','32':'6','33':'9','34':'12','35':'15','36':'28','37':'21','38':'24','39':'27',
'40':'0','41':'4','42':'8','43':'12','44':'16','45':'20','46':'24','47':'28','48':'32','49':'36',
'50':'0','51':'5','52':'10','53':'15','54':'20','55':'25','56':'30','57':'35','58':'40','59':'45',
'60':'0','61':'6','62':'12','63':'18','64':'24','65':'30','66':'36','67':'42','68':'48','69':'54',
'70':'0','71':'7','72':'14','73':'21','74':'28','75':'35','76':'42','77':'49','78':'56','79':'63',
'80':'0','81':'8','82':'16','83':'24','84':'32','85':'40','86':'48','87':'56','88':'64','89':'72',
'90':'0','91':'9','92':'18','93':'27','94':'36','95':'45','96':'54','97':'63','98':'72','99':'81'
};

var adc = {
'000':'0','001':'1','002':'2','003':'3','004':'4','005':'5','006':'6','007':'7','008':'8','009':'9',
'010':'1','011':'2','012':'3','013':'4','014':'5','015':'6','016':'7','017':'8','018':'9','019':'10',
'020':'2','021':'3','022':'4','023':'5','024':'6','025':'7','026':'8','027':'9','028':'10','029':'11',
'030':'3','031':'4','032':'5','033':'6','034':'7','035':'8','036':'9','037':'10','038':'11','039':'12',
'040':'4','041':'5','042':'6','043':'7','044':'8','045':'9','046':'10','047':'11','048':'12','049':'13',
'050':'5','051':'6','052':'7','053':'8','054':'9','055':'10','056':'11','057':'12','058':'13','059':'14',
'060':'6','061':'7','062':'8','063':'9','064':'10','065':'11','066':'12','067':'13','068':'14','069':'15',
'070':'7','071':'8','072':'9','073':'10','074':'11','075':'12','076':'13','077':'14','078':'15','079':'16',
'080':'8','081':'9','082':'10','083':'11','084':'12','085':'13','086':'14','087':'15','088':'16','089':'17',
'090':'9','091':'10','092':'11','093':'12','094':'13','095':'14','096':'15','097':'16','098':'17','099':'18',
'100':'1','101':'2','102':'3','103':'4','104':'5','105':'6','106':'7','107':'8','108':'9','109':'10',
'110':'2','111':'3','112':'4','113':'5','114':'6','115':'7','116':'8','117':'9','118':'10','119':'11',
'120':'3','121':'4','122':'5','123':'6','124':'7','125':'8','126':'9','127':'10','128':'11','129':'12',
'130':'4','131':'5','132':'6','133':'7','134':'8','135':'9','136':'10','137':'11','138':'12','139':'13',
'140':'5','141':'6','142':'7','143':'8','144':'9','145':'10','146':'11','147':'12','148':'13','149':'14',
'150':'6','151':'7','152':'8','153':'9','154':'10','155':'11','156':'12','157':'13','158':'14','159':'15',
'160':'7','161':'8','162':'9','163':'10','164':'11','165':'12','166':'13','167':'14','168':'15','169':'16',
'170':'8','171':'9','172':'10','173':'11','174':'12','175':'13','176':'14','177':'15','178':'16','179':'17',
'180':'9','181':'10','182':'11','183':'12','184':'13','185':'14','186':'15','187':'16','188':'17','189':'18',
'190':'10','191':'11','192':'12','193':'13','194':'14','195':'15','196':'16','197':'17','198':'18','199':'19'
} 

Array.prototype.isEmpty = function() {
  return (''+this) === '';
}

function add(a, b, c) {
  var r = '', s = '';
  a = a.split("").reverse();
  b = b.split("").reverse();
  while (!a.isEmpty() || !b.isEmpty() || c !== '0') {
    x = a.isEmpty() ? '0' : a.shift();
    y = b.isEmpty() ? '0' : b.shift();
    s = adc[c + x + y];
    s = s.split("").reverse();
    r = (s.shift()) + r;
    c = (s.isEmpty()) ? '0' : '1';
  }
  return r;
}

function mult(a, b) {
  var s = '0';
  var m = '';
  b.split('').reverse().forEach(function(e) {
    var z = m;
    a.split('').reverse().forEach(function(f) {
      s = add(s, mul[e + f] + z, '0');
      z = z + '0';
    });
    m = m + '0';
  } );
  return s;
}

function test(a, b) {
  var t0 = (new Date()).getTime();
  var r = mult(a,b);
  var t1 = (new Date()).getTime();
  var e = t1 - t0;
  console.log('mult ' + a + ' * ' + b + ' = ' + r + " (" + e + " ms)");
}

test('12345', '42');
test('9999999999', '9999999999');

Questo produce:

mult 12345 * 42 = 518490 (3 ms) 
mult 9999999999 * 9999999999 = 99999999980000000001 (47 ms) 

2

Haskell 507 496

Questo funziona con numeri interi arbitrariamente grandi. Definisco rappresentazioni personalizzate per i numeri naturali da 0 a 18 (il numero naturale più grande uguale alla somma di due cifre) e definisco la moltiplicazione little-endian in termini di moltiplicazione numero *, che definisco in termini di numero + aggiunta di numeri , che definisco in termini di cifra + somma cifre. Ho una funzione di riduzione che espande 10--18 valori nella loro decomposizione digitale. Questo quindi legge e inverte le due stringhe, si traduce in associazioni personalizzate, si moltiplica e si traduce indietro, invertendo per ottenere il risultato giusto.

Modifica 2

Ho salvato alcuni caratteri creando brevi alias locali per comandi multi-carattere che uso più di una volta, oltre a rimuovere spazi e parentesi e sostituendo (- )coppie con $quando possibile.

data S=Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R deriving(Enum, Ord, Eq)
p Z=id
p x=succ.p(pred x)
s Z=id
s x=pred.s(pred x)
z=s J
r[]=[]
r(x:y)|x<J=x:r y
r(x:[])=z x:[A]
r(x:y)=z x:(r$p A a:b)where(a:b)=r y
a x y=r$w(r x)(r y)
m Z _=[]
m _[]=[]
m x y=r$a y(m(pred x)y)
t[]_=[Z]
t _[]=[Z]
t(x:z)y=r$a(m x y)(Z:r(t z y))
i '0'=Z
i x=succ.i.pred$x
b Z='0'
b x=succ.b.pred$x
w[]y=y
w x[]=x
w(x:c)(y:d)=p x y:(w c d)
o=map
v=reverse
f=(o i).v
g=v.o b
main=getLine>>=putStrLn.(\[x,y]->g$t(f x)(f y)).words

Per riferimento, S è il tipo di dati personalizzato simile a un numero intero, pè 'più' (aggiunta cifra + cifra), sè sottratto (per riduzione), rè ridotto (espandi in decomposizione digitale), aè aggiunta (aggiunta numero + numero), mè moltiplicare (cifra * moltiplicazione numerica), tè volte (numero * moltiplicazione numerica), iè 'interpretare' (converte la stringa in elenco di S), bè 'indietro' (elenco di S in stringa), e f e g sono solo accorciamenti per il golf scopi. Non ho usato i numeri, neanche implicitamente; il più vicino che ho ottenuto è stato l'utilizzo di successori e predecessori, che sono concetti matematici di livello molto più elevato rispetto all'aggiunta e alla moltiplicazione dei numeri naturali.

modificare

Hai dimenticato di includere il profilo temporale.

> time echo "9999999999 9999999999" | runhaskell multnonum.hs
99999999980000000001

real    0m0.246s
user    0m0.228s
sys     0m0.012s

Solo per buona misura:

> time echo "99999999980000000001 99999999980000000001" | runhaskell multnonum.hs
9999999996000000000599999999960000000001

real    0m0.244s
user    0m0.224s
sys     0m0.016s

Andiamo pazzi!

> time echo "9999999996000000000599999999960000000001 9999999996000000000599999999960000000001" | runhaskell multnonum.hs
99999999920000000027999999994400000000699999999944000000002799999999920000000001

real    0m0.433s
user    0m0.424s
sys     0m0.004s

conferma


1

Python 2 - 1165, 712, 668 664

I,T,V,N,X,J=raw_input,dict,reversed,None,zip,''.join
D='0123456789'
z,o='01'
A,B=I(),I()
r=i=""
K=map(J,X('666622222222911111551111555884444447773333333','678945672389954132987698765898967457989837654'))
P=T(X(K,map(J,X('344501110011800000440000332673322124652202211','628480244668154132507698505422648609367491852'))))
S=T(X(K,'cdef678945abi65243ed87a9cbaghcdab89egfcb6a987'))
for d in D:P[z+d]=z;S[z+d]=d
def Z(A,B,R=r):
 for a,b in V(map(N,V(z+A),V(z+B))):c=(a or z)+(b or z);s=S[min(c)+max(c)];R=Z(R,o)+T(X('abcdefghi',D))[s]if s>"?"else R+s
 return R
for a in V(A):
 j=""
 for b in V(B):r=Z(r,P[min(a+b)+max(a+b)]+i+j).lstrip(z);j+=z
 i+=z
print r if r else z

Si noti che non sto usando l'indicizzazione logica come Z = [X, Y][N == "0"], perché questo potrebbe essere interpretato come un booleano lanciato in un indice numerico.

Ungolfed:

A = raw_input()
B = raw_input()

P = {'00':'00','01':'00','02':'00','03':'00','04':'00','05':'00','06':'00','07':'00','08':'00','09':'00',
     '10':'00','11':'01','12':'02','13':'03','14':'04','15':'05','16':'06','17':'07','18':'08','19':'09',
     '20':'00','21':'02','22':'04','23':'06','24':'08','25':'10','26':'12','27':'14','28':'16','29':'18',
     '30':'00','31':'03','32':'06','33':'09','34':'12','35':'15','36':'28','37':'21','38':'24','39':'27',
     '40':'00','41':'04','42':'08','43':'12','44':'16','45':'20','46':'24','47':'28','48':'32','49':'36',
     '50':'00','51':'05','52':'10','53':'15','54':'20','55':'25','56':'30','57':'35','58':'40','59':'45',
     '60':'00','61':'06','62':'12','63':'18','64':'24','65':'30','66':'36','67':'42','68':'48','69':'54',
     '70':'00','71':'07','72':'14','73':'21','74':'28','75':'35','76':'42','77':'49','78':'56','79':'63',
     '80':'00','81':'08','82':'16','83':'24','84':'32','85':'40','86':'48','87':'56','88':'64','89':'72',
     '90':'00','91':'09','92':'18','93':'27','94':'36','95':'45','96':'54','97':'63','98':'72','99':'81',
     }
S = {'00':'0','01':'1','02':'2','03':'3','04':'4','05':'5','06':'6','07':'7','08':'8','09':'9',
     '10':'1','11':'2','12':'3','13':'4','14':'5','15':'6','16':'7','17':'8','18':'9','19':'a',
     '20':'2','21':'3','22':'4','23':'5','24':'6','25':'7','26':'8','27':'9','28':'a','29':'b',
     '30':'3','31':'4','32':'5','33':'6','34':'7','35':'8','36':'9','37':'a','38':'b','39':'c',
     '40':'4','41':'5','42':'6','43':'7','44':'8','45':'9','46':'a','47':'b','48':'c','49':'d',
     '50':'5','51':'6','52':'7','53':'8','54':'9','55':'a','56':'b','57':'c','58':'d','59':'e',
     '60':'6','61':'7','62':'8','63':'9','64':'a','65':'b','66':'c','67':'d','68':'e','69':'f',
     '70':'7','71':'8','72':'9','73':'a','74':'b','75':'c','76':'d','77':'e','78':'f','79':'g',
     '80':'8','81':'9','82':'a','83':'b','84':'c','85':'d','86':'e','87':'f','88':'g','89':'h',
     '90':'9','91':'a','92':'b','93':'c','94':'d','95':'e','96':'f','97':'g','98':'h','99':'i',
     }
L = {'a':'0','b':'1','c':'2','d':'3','e':'4','f':'5','g':'6','h':'7','i':'8'}

def strSum(A, B):
    R = ""
    for a, b in reversed(map(None, reversed("0" + A), reversed("0" + B))):
        if a == None: a = '0'
        if b == None: b = '0'
        s = S[a + b]
        if s.isdigit():
            R += s
        else:
            R = strSum(R, "1") + L[s]
    return R

i = ""
r = "0"
for a in reversed(A):
    j = ""
    for b in reversed(B):
        p = P[a + b] + i + j
        r = strSum(r, p)
        j += "0"
    i += "0"

r = r.lstrip("0")
if r == "":
    r = "0"

print r

Direi che l'uso delle funzioni min () e max () non dovrebbe essere consentito perché stanno confrontando i valori interi effettivi, vero?
WorldSEnder,

@WorldSEnder: direi che confrontano i personaggi, cosa consentita in questa sfida. ("Il confronto lessicografico dei caratteri è consentito.")
Falko,

1

Scala, 470 caratteri

( sono scala standard ma possono essere equivalentemente sostituiti con =>se stiamo contando i byte)

def p(a: String,b: String)={type D=List[Char]
val d="0123456789".toList
def v(s: String)=s.toList.map{c⇒d.takeWhile(c.!=)}
def u(l:D, a:D):(Char,D)=l match {
case _::_::_::_::_::_::_::_::_::_::m⇒u(m,'a'::a)
case _⇒(('a'::l).zip(d).last._2,a)}
val o=(("", List[Char]())/:v(a).tails.toList.init.map{l⇒(v(b) map {_.flatMap(_⇒l.head)})++l.tail.map(_⇒Nil) reverse}.reduce(_.zipAll(_, Nil, Nil).map{t⇒t._1++t._2}))({(t,e)⇒val s=u(t._2++e,Nil);(s._1+t._1,s._2)})
u(o._2, Nil)._1+o._1}

Qui stiamo emulando cifre usando la lunghezza degli elenchi, facendo attenzione a non usare alcuna operazione numerica - solo pieghe, mappe, zip e simili. Un numero è un elenco di queste cifre (ordine invertito strategicamente a metà del calcolo); moltiplichiamo le singole cifre con flatMape le nostre righe aumentano con reduce. ugestisce capire il carry (facendo corrispondere direttamente con un elenco di> 10 elementi e ricorrendo) e convertendo le cifre in caratteri, e usiamo a /:per farci strada attraverso lo stack con quello. L'esempio richiesto viene completato in meno di un secondo.

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.