Multipliez deux nombres sans utiliser de nombres

30

On vous donne en entrée deux chaînes représentant des entiers positifs en base 10, tels que "12345"et "42". Votre tâche consiste à sortir une chaîne contenant leur produit, "518490"dans ce cas.

La torsion est que vous ne pouvez pas utiliser de types numériques dans votre code. Non ints, floats, unsigned longs, etc., pas de types de nombres complexes intégrés ou d'entiers de précision arbitraires, ou quoi que ce soit dans ce sens. Vous n'utilisez pas beaucoup de littéraux de ces types, ni aucune fonction, méthode, opérateur, etc. qui les renvoie.

Vous pouvez utiliser des chaînes, des booléens, des tableaux ou tout autre élément qui ne serait normalement pas utilisé pour représenter un nombre. (Mais notez que ni l'indexation dans un tableau ni l'obtention de sa longueur ne seront probablement possibles sans invoquer un type numérique.) charS sont autorisés, mais vous ne pouvez effectuer aucune opération arithmétique ou au niveau du bit sur eux ou les traiter autrement comme autre chose que un jeton représentant une partie d'une chaîne. (La comparaison lexicographique de chars est autorisée.)

Vous ne pouvez pas contourner la restriction. Cela inclut (mais sans s'y limiter) l'utilisation de types numériques à l'intérieur d'une evalfonction de type, les conversions implicites de types en types numériques, l'utilisation d'opérateurs numériques ou au niveau du bit sur les types non numériques qui les prennent en charge, l'utilisation de types numériques stockés à l'intérieur de types de conteneurs, ou l'appel de fonctions ou programmes externes qui renvoient des résultats numériques sous forme de chaîne. (Je me réserve le droit d'ajouter à cette liste si d'autres solutions de contournement apparaissent dans les réponses.) Vous devez implémenter la multiplication vous-même en utilisant uniquement des types non numériques.

L'entrée et la sortie peuvent se faire par n'importe quelle méthode pratique, tant que les données entrent et sortent de votre code sous la forme d'une chaîne. Vous pouvez supposer que chacun des deux arguments d'entrée ne contient que les caractères ASCII [0-9]et ne commencera pas par 0. Votre sortie ne doit pas non plus comporter de zéros non significatifs.

Une dernière chose: votre code doit gérer correctement les entrées d' au moins 10 caractères et doit s'exécuter en moins d'une minute sur un ordinateur moderne pour toutes les entrées de cette plage. Avant de poster, veuillez vérifier que lorsque vous avez reçu des entrées 9999999999et 9999999999, votre programme donne une sortie de 99999999980000000001, en moins d'une minute. Cette restriction existe spécifiquement pour empêcher les réponses qui fonctionnent en allouant un tableau de taille a*bpuis en itérant dessus, donc gardez à l'esprit que les réponses de ce formulaire ne seront pas éligibles pour gagner.

Il s'agit de , donc la solution valide la plus courte (en octets) l'emporte.

Nathaniel
la source
Pouvons-nous accepter "12345"de STDIN plutôt que 12345? Ou pouvons-nous accepter les deux numéros comme "12345", "42"?
Justin
Ma première pensée était d'écrire une fonction prenant des arguments de chaîne de longueur met net retourner un argument de longueur m*n. Mais comme les chaînes doivent littéralement contenir la représentation ASCII des nombres, je suppose que c'est contraire aux règles.
Level River St,
1
@xnor dans de nombreuses langues, il pourrait être plus court d'écrire tous les cas. Mais j'ai trouvé cette façon en Python:a,b="0123456789x".split('0');c=iter(b).next() if c=='x': c='0'
Nathaniel
1
ou en 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'))
Justin

Réponses:

6

Haskell - 180 206 214 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

Met en œuvre la multiplication via des ajouts répétés, et toutes sortes de magie des chiffres sont gérées en décalant et en filtrant la ['0'..'9']liste. Définit un opérateur #du type String -> String -> String:

*> :set +s
*> "9990123456789"#"9999876543210"
"99900001219316321126352690"
(0.02 secs, 9862288 bytes)
mniip
la source
On dirait que nous avons un nouveau gagnant! (Bien que comme avant, je ne puisse pas lire Haskell de ce degré de sophistication - quelqu'un peut-il vérifier indépendamment qu'il répond aux spécifications?)
Nathaniel
(De plus, le ['0' .. '9'] ressemble un peu au traitement implicite des caractères comme des nombres qui peuvent être itérés - existe-t-il un moyen court de générer cette liste à partir de la chaîne "0123456789" à la place?)
Nathaniel
@Nathaniel Eh bien tout d'abord la chaîne "0123456789" est la liste ['0'..'9']. Deuxièmement, dans Haskell [a..b] est une énumération, les types qui ont déclaré des instances de la Enumclasse de types peuvent être énumérés comme ça, et la déclaration décrit comment fonctionne l'énumération. Bool, le type booléen a également une instance, et vous pouvez donc également le faire [False..True]. Il n'y a pratiquement pas de chiffres impliqués.
mniip
14

sed, 339 338 octets

Je sais que c'est un ancien, mais je parcourais et cela a piqué mon intérêt. De quoi s'enregistrer en tant qu'utilisateur! Je suppose que j'ai été influencé par " Je voudrais bien voir une solution complète sed - 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

Ce script sed attend deux nombres décimaux en entrée, séparés par un espace

tests:

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

Vous pouvez reconnaître les deux derniers comme RSA-100 (50 x 50 chiffres) et RSA-768 (116 x 116 chiffres).

En utilisant GNU sed sur un système pas très moderne (Intel Core 2 de l'ère 2007), le dernier de ceux-ci prend plus d'une minute, mais il arrive plus rapidement sur un processeur plus récent:

  • Q6600:> 1 minute
  • i7-3770: 26 secondes
  • i7-6700: 22 secondes

La multiplication chétive à 10 chiffres spécifiée dans la question prend bien moins d'une seconde sur l'un d'entre eux (bien qu'il soit plein de neuf pathologiques).

Je crois que c'est standard sed, sans extensions. POSIX garantit un espace de 8192 octets uniquement, ce qui nous limite à multiplier les nombres à 400x400 chiffres, mais les implémentations peuvent en fournir davantage. GNU sed n'est limité que par la mémoire disponible, donc pourrait gérer quelque chose de beaucoup plus gros, si vous êtes prêt à attendre.

Et je suis convaincu que j'ai respecté les règles - c'est presque une donnée dans une langue qui n'a pas de chiffres. :-)

Explication

J'utilise un hybride unaire / décimal, convertissant les nombres décimaux en une séquence unaire:

 42 => _xxxx_xx

En décimal unaire, l'addition est facile. Nous itérons du chiffre le moins significatif au chiffre le plus significatif, en concaténant les x:

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

Nous supprimons ensuite les espaces blancs et traitons le report en convertissant 10 x consécutifs en l'une des unités suivantes:

 _xxxxxxxxxx_xxxxxx_xxxxxxxxxxx       10.6.11
 _xxxxxxxxxx_xxxxxxx_x                10.7.1
 _x__xxxxxxx_x                        1.0.7.1 

Une fois que nous avons l'addition, la multiplication est possible. Nous multiplions x * y en considérant le dernier chiffre de y. Ajoutez x à l'accumulateur autant de fois, puis passez au chiffre suivant et décalez x d'une décimale vers la gauche. Répétez jusqu'à ce que y soit zéro.

Code développé

#!/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
Toby Speight
la source
1
Réponse très satisfaisante, merci!
Nathaniel
9

sed, 379 octets

Le mérite de cette brillante réponse revient à @LuigiTiburzi via Unix et Linux.SE: https://unix.stackexchange.com/a/37213/34061 . Je suis tombé sur ce sujet il y a quelques jours:

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

Explication générale

  • Séparez chaque chiffre. ainsi 12*3devient<1<2*<3
  • Convertissez chaque chiffre en ce nombre de |caractères. ainsi <1<2*<3devient<|<||*<|||
  • Remplacez à plusieurs reprises |<par <||||||||||afin de décaler les décimales supérieures vers la position des unités. ainsi <|<||*<|||devient<||||||||||||*<|||
  • Retirez <. ainsi <||||||||||||*<|||devient||||||||||||*|||
  • Retirez 1 |de la RHS du *. ainsi ||||||||||||*|||devient||||||||||||*||
  • Remplacez à plusieurs reprises chacun |sur le RHS par tous les |sur le LHS. Cela a pour effet de multiplier le nombre LHS et RHS de |pour donner le numéro de produit de | Ainsi ||||||||||||*||devient||||||||||||||||||||||||||||||||||||*
  • Retirez *. ainsi ||||||||||||||||||||||||||||||||||||*devient||||||||||||||||||||||||||||||||||||
  • convertir le nombre de |retour en décimal par l'inverse des premières étapes. Ainsi ||||||||||||||||||||||||||||||||||||devient 36.

Sortie:

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

Malheureusement, il échoue lamentablement sur l'exigence de temps - 200*1000prend 41 secondes sur ma machine virtuelle Ubuntu, et l'exécution semble empiriquement augmenter avec le carré du produit final.

Traumatisme numérique
la source
1
Ceci est presque équivalent algorithmiquement à ma réponse JS supprimée, à l'exception de la reconversion en partie numérique.
Optimizer
@Optimizer Accepté. La différence est que la vôtre utilise length()qui renvoie un nombre. Celui-ci utilise une substitution purement regex sans type numérique. Je pense que votre réponse est potentiellement gagnante si vous pouvez supprimer le length()- peut-être pourriez-vous faire une substitution de regex similaire à la place?
Digital Trauma
1
Très bien, mais la restriction d'une minute est spécifiquement destinée à empêcher les solutions qui fonctionnent en comptant jusqu'à la réponse. J'aimerais tout de même voir une solution sed complète.
Nathaniel
1
J'ai une réponse qui fonctionne sur de grands nombres (par exemple plus grand que l'espace d'adressage du système).
Toby Speight
@TobySpeight oui, très bien. Je pense que je dois avoir déjà voté un peu plus tôt :)
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")

Si (beaucoup) de zéros non significatifs sont autorisés, les 12 derniers caractères ne sont pas nécessaires.

Cela effectue essentiellement la multiplication standard à la main. Les chiffres sont représentés comme des chaînes de Is répétés (comme les chiffres romains primitifs). Les nombres sont représentés sous forme de listes de chiffres dans l'ordre inverse. L'ajout de chiffres uniques est effectué en cocaténant les chaînes et en supprimant dix Is si nécessaire.

Voici une version non golfée:

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())
Wrzlprmft
la source
1
Quelle est cette sorcellerie! Comment ça marche! Sensationnel. En outre, voici un autre golf que vous pourriez faire: def A(x,y):\n S=[];o=""-> def A(x,y,S=[],o=""):. De plus, malheureusement, ce ["","1"][t in i]n'est pas autorisé; il utilise un booléen pour indexer, le traitant comme un nombre. Je pense que cela t in i and"1"or""devrait fonctionner.
Justin
@Quincunx: Définir Scomme un argument avec un défaut n'aurait pas fonctionné, car ce serait toujours la même liste même pour différents appels de la fonction et donc pas réinitialisé []. Vous aviez raison ["","1"][t in i], j'ai corrigé cela. J'ai également ajouté une explication.
Wrzlprmft
C'est assez étonnant. Il obtient la coche verte pour l'instant. (J'ai édité la question pour clarifier que les zéros non significatifs dans la sortie ne sont pas autorisés - désolé!)
Nathaniel
7

Rubis: 752 698

C'est juste pour obtenir une réponse, juste par curiosité. Édité: maintenant un peu joué au golf.

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

Utilisation: je l'avais dans un fichier appelé peasant.rb:

$ time ruby peasant.rb 9999999999 9999999999
99999999980000000001

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

Explication: c'est la multiplication paysanne, donc je divise et double à plusieurs reprises. La réduction de moitié se fait en divisant par deux les chiffres et en marquant les restes comme suit: 1234 -> 0b1a1b2a; puis recherchez et remplacez sur les b: 06a17a; puis nettoyage -> 617.

L'addition se fait comme ça ... tout d'abord, je rembourre les deux cordes à la même longueur et fais des paires à partir des chiffres. Ensuite, j'ajoute les chiffres en construisant une chaîne qui a la longueur de chaque chiffre et en concaténant; Je supprime une chaîne de cette longueur au début de «0123456789abcdefghij», puis je conserve le premier caractère. Ainsi, par exemple, "9" + "9" -> "i". NB J'évite réellement d'utiliser des fonctions de longueur ici pour éviter complètement les types de nombres; la suppression du préfixe se fait à la place avec une expression rationnelle.

Alors maintenant, j'ai une chaîne contenant un mélange de chiffres et de lettres. Les lettres représentent des nombres avec un chiffre de retenue; J'ajoute 0 au nombre, puis je remplace à plusieurs reprises les motifs chiffres-lettres par le résultat du report jusqu'à ce que l'ajout soit terminé.

bazzargh
la source
1
Réponse très intelligente, exactement le genre de chose que j'espérais voir!
Nathaniel
1
J'espère que quelqu'un en affichera un avec des chiffres de l'Église!
bazzargh
Ce serait cool, mais je ne suis pas sûr que cela fonctionnerait avec l'exigence d'efficacité - je pense que la conversion entre les chaînes et les chiffres de l'Église impliquerait effectivement de compter jusqu'à 9999999998000000000001.
Nathaniel
7

Brainfuck (1328 octets)

Considérations dans un premier temps:

  • Je ne sais pas si brainfuck est une réponse valable à ces questions, car je ne sais pas si vous considérez les valeurs des cellules comme des `` types numériques '' ou non. Je ne pense pas car bf ne connaît pas les types, mais c'est ma propre opinion, veuillez me corriger si je me trompe.
  • Une implémentation prenant en charge des valeurs (presque) illimitées est nécessaire.
  • Cela pourrait être beaucoup trop lent, en fonction de la mise en œuvre.

Je n'ai testé le programme qu'avec mon propre interprète, vous pouvez le trouver ici .

L'entrée doit être les deux nombres séparés par un seul espace ASCII.

Golfé:

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

Non golfé:

,
>++++++[<----->-]<--
[                                           # 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
[<+>-]<[>>+>+<<<-]>>>[<<<+>>>-]<[[-]<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<-]>[<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<->>[-]]+>-]<-]<<+>]<[>>+<<-]>>[<<<[>+>+<<-]>>[<<+>>-]>-]<<[<<->>-]<[-]<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[>>]+[<<]>[>[>>]<+<[<<]>-]<<<<<<<<<<[>>+>+<<<-]>>>[<<<+>>>-]+[<+>-]<<<[-]>>[<<+>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+<<-]>>[<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<<->>>[-]]+>-]<-]<<<+>>]<[-]<<<<[-]>>>[<<<+>>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[<+>-]<]<[>+>+<<-]>>[<<+>>-]<[>+<[-]]+>[<[-]<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[[-]>>>>>>>>[>>]<[<[<<]<<<<<+>>>>>>>[>>]<-]<-<<[<<]<<<<<>++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<.[-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]+[<->-]<<<<<[-]>>>>[<<<<+>>>>-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]<[<+>-]<]<[-]]<[>>++++++[<++++++++>-]<.[-]<[-]]<[-]<[-]>>>>>>>>>>>>[>[-]>]<<[-<<]<<<<<<<<<<<<<<<<<[-]<[-]

J'ai pris le code pour la sortie de la valeur de cette réponse , merci à l'auteur pour cela!

Le programme n'est peut- être pas valide, mais dans les deux cas, je voulais le partager avec vous ^^

Mise à jour: Vous pouvez maintenant le tester (uniquement pour les petites multiplications) ici, grâce à la réponse de @ Sp3000 à ce concours et aux nouveaux extraits de pile de 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>

Chiffrer
la source
Je ne sais pas non plus si c'est valable! Je suppose que tout est un numéro dans Brainfuck, ou rien ne l'est.
Nathaniel
J'aime cette réponse. Je me suis amusé avec bf récemment. cela met en lumière le fait qu'au niveau de la machine, tout n'est que des jetons de toute façon. Difficile de dire si cela suit vraiment les règles ou non.
Octopus
6

Python, 394 349 340 caractères

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

Courez comme:

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

Prend 50 millisecondes.

Utilise la multiplication des paysans russes . Lors de l'ajout de chiffres, nous les convertissons en unaires ('5' => [R, R, R, R, R]), concaténons les listes, puis reconvertissons. Uconvertit en unaire, en utilisant Rcomme chiffre unaire. Nous calculons b/=2comme b=b*5/10.

Keith Randall
la source
Quelques golfs: def A(a,b):\n r='';c=[]-> def A(a,b,r='',c=[]):, de même pour def M. Vous pouvez peut-être passer for z in D:d.pop()\n c=['X']à [d.pop()for z in D];c=['X'], auquel cas vous pouvez même le réduire au précédent if. En outre, peut-il if list(b).pop()in'13579'simplement être if b[:].pop()in'13579'?
Justin
@Quincunx: Merci. La dernière ne fonctionnera pas car la première itération best une chaîne, pas une liste.
Keith Randall
Vous pouvez sauter Met écrire un programme complet; a,b=input() est autorisée.
Justin
1
b * 5/10 est une bonne astuce.
bazzargh
Je viens de tombé sur reduce, ce qui vous permet de nicen A(b,A(b,A(b,A(b,b))))à reduce(A,[b,b,b,b,b]). Malheureusement, cela n'affecte pas le nombre de caractères.
Wrzlprmft
5

JavaScript (E6) 375 395 411 449

Edit Golfed
Edit Bug corrigé: manque d'effacement d'un indicateur de portage

Cela peut être fait avec une simple manipulation de symboles en un temps proche de 0.
Dans cette version, vous pouvez utiliser n'importe quel caractère au lieu des chiffres, tant que le symbole est dans l'ordre croissant.

Remarques: utilisation de chaînes, hashmap avec clé de chaîne, tableaux utilisés comme liste. Pas d'indexation, les tableaux sont parcourus en utilisant 'map' ou tournés en utilisant push & shift.
Tous les «+» sont des concaténations de chaînes.

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)

Moins de golf ( peut-être une explication demain)

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

Tester dans la console FireFox / FireBug

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

Sortie

Result 99999999980000000001 time ms 14
edc65
la source
Il y a peut-être un léger bug - la sortie de l' 9999999999affaire devrait être 99999999980000000001, non99999999980000000081
Nathaniel
:( va vérifier
edc65
Si vous utilisez des tables de multiplication, comment contournez-vous le fait que la sommation n'est pas autorisée?
COTO
1
La sommation EST autorisée à l'aide d'une table de hachage (s dans le code). Ex. s ['34 '] ->' 7 '. Juste des symboles, pas des chiffres. Pourrait être s ['cd'] -> 'g'
edc65
5

Haskell, 231 octets

Ceci définit un opérateur # qui multiplie deux représentations de chaînes de nombres naturels. Il fonctionne en définissant une opération élémentaire d'incrémentation / décrémentation sur les chaînes, puis l'utilise pour construire l'addition et la multiplication. Un peu de magie supplémentaire donne des accélérations exponentielles qui rendent tout cela possible.

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

Cette approche est suffisamment rapide pour que même sur un ordinateur portable 2008 dans le ghci REPL non optimisé, le cas de test ne prenne qu'une fraction de seconde:

λ> :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)

Voici une vérification que tous les produits à deux chiffres sont corrects:

λ> and [ show (x * y) == (show x # show y) | x <- [0..100], y <- [0..100] ]
True
Matt Noonan
la source
On dirait que nous avons un nouveau leader! (Je ne peux pas lire Haskell cependant - quelqu'un peut-il confirmer indépendamment qu'il correspond à la spécification?)
Nathaniel
1
Oui, c'est un haskell parfaitement cromulent, il correspond aux spécifications et fonctionne comme annoncé. Bon travail!
bazzargh
4

Bash + ImageMagick: 52

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

Attend que l'entrée soit dans les variables du shell aetb . Ce n'est pas particulièrement intelligent ou efficace, mais cela fait le travail. Cela a probablement déjà été fait.

Notez que le x dénote les dimensions de l'image; ce n'est pas un opérateur arithmétique dans ce contexte.

Je n'ai pas testé cela, mais je suis prêt à supposer que pour une entrée non extrême, cela se terminera en moins d'une minute. Je peux le tester demain.

En cas de problème avec les versions d'ImageMagick, c'est celle que j'utilise: ImageMagick 6.7.7-10

millinon
la source
Bien essayé, mais je suis certain que cela ne fonctionnera pas en moins d'une minute (ou du tout sur n'importe quelle machine existante) pour les entrées 9999999999et 9999999999.
Nathaniel
4
Cela fonctionne aussi: dd if=/dev/zero bs=$a count=$b 2>&-|wc -c.
jimmy23013
1
Une 9999999999x9999999999image au format 8 bits occupera tout l'espace du disque dur qui existe actuellement sur Terre. Bien sûr, un png serait beaucoup plus petit, si vous pouvez le créer sans d'abord créer l'image brute. (Bien que je soupçonne fortement que vous auriez des problèmes de débordement d'entier avec une image de cette taille.) Mais quand même, une telle méthode tomberait presque certainement dans la faille de l'appel des choses qui renvoient les résultats numériques en tant que chaînes.
Nathaniel
1
Vous pouvez enregistrer 2 octets en utilisant $bau lieu de ${b}.
nyuszika7h
1
En outre, vous pouvez enregistrer 5 octets en utilisant grep -vc gau lieu de grep -v g|wc -l.
nyuszika7h
2

Python 2 (preuve de concept)

Cette solution fonctionne en utilisant uniquement des chaînes et des listes, et une petite expression régulière. Je crois que cela correspond parfaitement aux spécifications, sauf qu'il n'y a aucun moyen que cela puisse faire 9999999999x9999999999en une minute. Bien que suffisamment de temps, cela fonctionnerait. Il peut multiplier les nombres à 4 chiffres assez rapidement.

Puisqu'il est techniquement invalide, je n'ai pas encore pris la peine de jouer au golf complètement. Je le ferai si les règles changent.

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

Exemples:

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

multiply('1869','1243') #returns the string 2323167
Loisirs de Calvin
la source
1
+1 parce qu'il répond aux spécifications (en dehors de l'exigence d'efficacité) pour autant que je sache
Nathaniel
2

Python 2 (555)

Normalement, je ne répondrais pas à mon propre défi aussi rapidement (ou pas du tout), mais je voulais prouver que cela pouvait être fait. (Heureusement, d'autres réponses l'ont fait avant celle-ci, mais je ne pouvais m'empêcher de vouloir le terminer.) Il y a encore du golf qui pourrait être fait, mais je pense que c'est raisonnable. Il gère le 9999999999x9999999999boîtier en moins de 0,03s sur ma machine.

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

Exemple d'utilisation: m("12345","42")

Cela fonctionne en faisant une longue multiplication en utilisant des manipulations de chaînes. Parfois, les variables sont des chaînes et parfois ce sont des itérateurs sur les chaînes, ce qui permet d'obtenir le premier élément sans utiliser un littéral entier. Tout est stocké avec les chiffres inversés, de sorte que le premier élément est le chiffre le moins significatif.

Voici une explication fonction par fonction:

  • ret ssont des fonctions de comptabilité. ( rest juste un alias pour reversed, qui fait un itérateur inverse et sconvertit les itérateurs en chaînes.)

  • iincrémente le nombre dans une chaîne de 1, y compris les cas comme 39+1=40et 99+1=100.

  • bajoute xet y, mais ne ydoit comporter qu'un seul chiffre. Il fonctionne en incrémentant les x ytemps.

  • aajoute deux numéros ensemble qui peuvent tous deux avoir plusieurs chiffres, en appelant bpour chaque chiffre entrant y.

  • nmultiplie xet y, mais ne ydoit être qu’un seul chiffre. Il fonctionne en ajoutant xà lui - même ytemps.

  • omultiplie xet y, où les deux arguments peuvent avoir plusieurs chiffres. Il utilise une longue multiplication classique

  • mconvertit simplement ses entrées de chaîne en itérateurs inversés et les leur remet o, puis inverse le résultat et le convertit en chaîne.

Nathaniel
la source
Golfs en couple: def a(x,y):-> def a(x,y,z=''):et supprimez la ligne suivante; astuces similaires pour d'autres fonctions, dans def o(x,y):, changez le x=s(x)en x=s(x);l='';z='', dans celui pour la boucle, supprimez de la même manière les sauts de ligne +; utilisez plutôt ;. De plus, je pense que cela if h!='0':h+=s(x)\nelse:h+=i(x)peut être tout simplement h+=h!='0'and i(x)or s(x); peut-être même h+=(h!='0'and i or s)(x); sinon, changez simplement en if'0'!=h. Des choses comme def r(x):return reversed(x)->r=reversed
Justin
Aussi, j'ai oublié de mentionner pour s, m: s=lambda x:''.join(x), m=lambda x,y:s(r(o(r(x),r(y))))au lieu de la déclaration de fonction entière. Avec juste ce que je sais fonctionner, cela ramène votre nombre d'octets à 521.
Justin
Oh, et un de plus: pour vos forboucles: 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), bien que cela puisse changer considérablement la vitesse de votre programme.
Justin
@Quincunx merci! Je peux également voir quelques autres améliorations ce matin. (Principalement, imbriquer les boucles au lieu de définir des fonctions.) Je ferai ces changements si des réponses plus compétitives apparaissent, ce qui semble probable - actuellement, elles me mettraient en tête, ce qui semble un peu injuste car c'était ma question et je '' ai eu plus de temps pour y penser.
Nathaniel
2

JavaScript: 3710 3604 octets

  • Utilisation de tables de recherche de chaînes avec multiplication à 1 chiffre et ajout avec report.
  • La multiplication se fait par chiffre x chiffre au lieu du chiffre x ligne.

Le 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 golfé avec des tests:

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

Cela produit:

mult 12345 * 42 = 518490 (3 ms) 
mult 9999999999 * 9999999999 = 99999999980000000001 (47 ms) 
Stephen Quan
la source
2

Haskell 507 496

Cela fonctionne pour des entiers arbitrairement grands. Je définis des représentations personnalisées pour les nombres naturels de 0 à 18 (le plus grand nombre naturel égal à la somme de deux chiffres), et je définis la multiplication en petits nombres en termes de multiplication chiffre * nombre, que je définis en termes de nombre + addition de nombre , que je définis en termes d'addition chiffre + chiffre. J'ai une fonction de réduction qui étend les valeurs 10 à 18 dans leur décomposition numérique. Cela lit et inverse simplement les deux chaînes, se traduit par les liaisons personnalisées, se multiplie et se traduit en arrière, inversant pour obtenir le bon résultat.

Modifier 2

J'ai enregistré quelques caractères en créant de courts alias locaux pour les commandes à plusieurs caractères que j'utilise plusieurs fois, ainsi qu'en supprimant les espaces et les parenthèses, et en remplaçant (- )paires par$ , si possible.

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

Pour référence, S est le type de données de type entier personnalisé, pest «plus» (chiffre + addition de chiffre), sest soustrait (pour réduction), rest réduit (se développe en décomposition numérique), aest addition (nombre + addition de nombre), mest multiplier (multiplication de chiffres * nombres), test multiplié par (multiplication de nombres * nombres),i est 'interpréter' (convertir la chaîne en liste S),b est 'en arrière' (liste de S en chaîne), et f et g ne sont que des raccourcis pour le golf fins. Je n'ai pas utilisé de chiffres, même implicitement; le plus proche que j'ai obtenu était d'utiliser des successeurs et des prédécesseurs, qui sont des concepts mathématiques de niveau beaucoup plus élevé que l'addition et la multiplication de nombres naturels.

modifier

J'ai oublié d'inclure le profil horaire.

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

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

Juste pour faire bonne mesure:

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

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

Allons fou!

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

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

confirmation

archaephyrryx
la source
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

Notez que je n'utilise pas d'indexation logique comme Z = [X, Y][N == "0"], car cela pourrait être interprété comme un booléen transtypé en index numérique.

Non golfé:

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
Falko
la source
Je dirais que l'utilisation des fonctions min () et max () ne devrait pas être autorisée car elles comparent des valeurs entières réelles, n'est-ce pas?
WorldSEnder
@WorldSEnder: Je dirais qu'ils comparent les personnages, ce qui est autorisé dans ce défi. ("La comparaison lexicographique des caractères est autorisée.")
Falko
1

Scala, 470 caractères

(les scala sont standard mais peuvent être remplacés de manière équivalente par =>si nous comptons les octets)

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}

Ici, nous émulons des chiffres en utilisant la longueur des listes, en faisant attention à ne pas utiliser d'opérations numériques - uniquement des plis, des cartes, des zips et autres. Un nombre est une liste de ces chiffres (ordre stratégiquement inversé à mi-parcours du calcul); nous multiplions les chiffres individuels avec flatMapet nos rangées avec reduce. ugère le calcul du report (en le comparant directement à une liste de> 10 éléments et la récurrence) et la conversion des chiffres en caractères, et nous utilisons un /:pour travailler notre chemin à travers la pile avec cela. L'exemple requis se termine en moins d'une seconde.

lmm
la source