Decomporre un numero con bit-xor senza le cifre 0, 3, 7


20

Sfida

Scrivi una funzione o un programma che accetta un numero decimale positivo, chiamalo A e genera due numeri positivi, B e C , in modo che:

  • A == B bitxor C
  • B e C non devono contenere nessuna delle cifre 0, 3 o 7 nella sua rappresentazione decimale.

Esempi

>>> decompose(3)
1, 2
>>> decompose(7)
1, 6
>>> decompose(718)
121, 695
>>> decompose(99997)
2, 99999
>>> decompose(4294967296)
4294968218, 922
>>> decompose(5296080632396965608312971217160142474083606142654386510789497504098664630388377556711796340247136376)
6291484486961499292662848846261496489294168969458648464915998254691295448225881546425551225669515922,
1191982455588299219648819556299554251659915414942295896926425126251962564256469862862114191986258666

Poiché la decomposizione non è unica, la tua funzione / programma non ha bisogno di produrre esattamente gli stessi risultati di questi esempi forniti.

Regole molto dettagliate

  1. Le presentazioni devono essere sotto forma di una funzione o un programma completi . importdichiarazioni non contano ai fini del punteggio finale.

  2. Si può presumere che l'ingresso A contenga sempre almeno una cifra di 0, 3 o 7.

  3. Si può presumere che esista sempre una decomposizione.

  4. Puoi usare BigInt se fanno parte delle librerie standard della lingua o possono essere installate tramite il gestore pacchetti de jure della lingua .

  5. La funzione dovrebbe essere veloce. Non dovrebbero essere necessari più di 20 secondi per essere eseguiti su un computer ragionevolmente moderno se alimentato con un numero di 100 cifre e non più di 2 secondi se alimentato con un numero di 10 cifre.

  6. La funzione / programma dovrebbe supportare input fino ad almeno 100 cifre .

    • Se la funzione / programma può supportare solo numeri interi fino a N <100 cifre, ci sarà una penalità di + 10 × (100 / N - 1) byte per il punteggio finale. Questo per incoraggiare i golfisti a supportare una gamma più ampia di numeri anche se l'importazione può essere dettagliata.
  7. Non ci sono restrizioni alla presentazione di input / output purché siano chiaramente in rappresentazione decimale.

    • La funzione può immettere e generare stringhe / BigInts se i tipi interi integrati non sono sufficienti.
    • L'input può provenire dal parametro della funzione, dall'argomento della riga di comando o da STDIN.
    • La funzione può restituire il risultato o semplicemente stampare il risultato direttamente su STDOUT.
    • Tuttavia, l'overflow con segno negli input / output non è consentito.
    • Le risposte approssimative non sono tollerate, gli input / output devono essere esatti.

punteggio

Questo è un . La soluzione più breve in byte vince.

C'è una penalità se il programma può supportare solo numeri inferiori a 100 cifre:

  • Numeri interi a 64 bit (19 cifre) = +42 byte
  • Numero intero a 63 bit (18 cifre) = +45 byte
  • Numeri interi a 53 bit (15 cifre) = +56 byte
  • Numeri interi 31/32 bit (9 cifre) = +101 byte

2
Sei sicuro che tale decomposizione sia sempre possibile? Puoi abbozzarmi una prova?
John Dvorak,

Qualcuno blocca 1, 5, 9 nella domanda 95 Movie Quotes allora.
jimmy23013,

3
100 cifre? ciò significa che Python vince subito, poiché è l'unico linguaggio comunemente usato qui che supporta numeri interi di precisione arbitraria. Perché non 19 cifre, che si inserisce in un numero intero senza 64 ma senza segno? (2 ^ 64 = 18 446 744 073 709 551 616)
Level River St

5
@steveverrill Mathematica ... GolfScript ... CJam ...
Martin Ender,

1
E Java (
dovevo

Risposte:


2

CJam, 70 byte

ri:Q{;Qmr_Q^`1$`+730`&}g_Q^p

Provalo online.

Seleziona casualmente numeri interi fino a quando non trova una corrispondenza. Questo a malapena rispetta il limite di 20 secondi per gli interi a 64 bit (utilizzando l'interprete Java), quindi ho aggiunto 42 al conteggio dei byte effettivi.

Esempio di esecuzione

$ cjam t <<< 7777777777; echo
2695665494
6161166119

10

Lisp comune, 240 224 183 173 169 byte

Il Lisp comune è un po 'prolisso per il golf. Tuttavia, questo decompone numeri di 100 cifre in meno di un secondo e numeri interi di 200 cifre in meno di dieci secondi, quindi non sono necessarie penalità. L'algoritmo è deterministico.

(defun s(z)(and #1=(some(lambda(q)(position q(format()"~a"z)))"037")(+ z(floor z(expt 10 #1#)))))
(defun d(x)(do((y x(or(s y)(s #3=(logxor x y))(return`(,y,#3#)))))(())))

L'alimentazione di riga tra le funzioni è solo a scopo tipografico. Test eseguito con l'ingresso di riferimento a 100 cifre:

(time (d 5296080632396965608312971217160142474083606142654386510789497504098664630388377556711796340247136376))
took 677,000 microseconds (0.677000 seconds) to run.
      20,989 microseconds (0.020989 seconds, 3.10%) of which was spent in GC.
During that period, and with 8 available CPU cores,
     671,875 microseconds (0.671875 seconds) were spent in user mode
           0 microseconds (0.000000 seconds) were spent in system mode
 54,221,104 bytes of memory allocated.
(1864921261592819619661568919418981552559955289196969112566252282429216186594265918444566258544614425
 5891958562486995519825158818455999516899524658151445485616155916296966645869599949958954491929662561)

Come bonus, sto includendo una versione del codice che costruisce in modo incrementale la soluzione dall'alto verso il basso. Può gestire un numero di 1000 cifre in meno di dieci secondi, ma non può competere nel golf a causa del codice aggiuntivo.

(defun decompose (x)
  (flet ((s (z)
           (mapcan #'(lambda (c) (and #1=(position c #2=(format () "~a" z))
                                 (list (- (length #2#) #1# 1))))
                   '(#\0 #\3 #\7))))
    (do ((y x (let ((p (nconc (s y) (s #3=(logxor x y)))))
                (or p (return`(,y,#3#)))
                (+ y (expt 10 (apply #'max p))))))
        (nil))))

* (time (decompose (parse-integer (make-string 1000 :initial-element #\7))))
took 9,226,000 microseconds (9.226000 seconds) to run.
        90,966 microseconds (0.090966 seconds, 0.99%) of which was spent in GC.
During that period, and with 8 available CPU cores,
     9,234,375 microseconds (9.234375 seconds) were spent in user mode
             0 microseconds (0.000000 seconds) were spent in system mode
 487,434,560 bytes of memory allocated.
(8889898889152488921298888992819221914229899249999918899888899888888889999989141219898898888988988898888888888899142442899924898918898898988988895189988898888924192198992454114198911989191888889898888918888988988998888891421118891899122898888998989898888898988898888999988918888898889189918889888888899888989219188898998888988892119889198888988888894888912188898989952999888888888898899998988898889228918998949999998898898991141888898999988912121292118899889998989899999892889941898888911888898889118998898888911889889888891452888998889288921141888888942189888899988891918889118888888888989892198899199914111188988889421111188889118888918989988912989999998989891119888898888888892621229888988888999619888952462219889189899998899888889989898891118989218888888898962988891188899888888888999888888888888888888888891269188921288888888998898899214191188888888898992188998898889919888889989889899988892115549998888898889218899988998911898989199918898918988898888891889888989119899888889888998918889112189998
 4184469818464841952189561886965821566229261221619858498284264289194458622668559698924621446851546256444641488616184155821914881485164244662156846141894655485889656891849662551896595944656451462198891289692696856414192264846811616261884188919426294584158925218559295881946496911489245664261126565546419851585441144861859822815144162828551969425529258169849412525611662488849586554989254181228254465226521648916188265491499166186964881248156451994924294646681548996645996894665198811511522424996844864211629888924642289925565591484541149414914699289441561496451494562955652129199261462268846144518142486845251946444998812988291119592418684842524648484689261441456645518518812265495165189812912919529151991611962525419626921619824496626511954895189658691229655648659252448158451924925658586522262194585891859285841914968868466462442488528641466655911199816288496111884591648442984864269495264612518852292965985888414945855422266658614684922884216851481646226111486498155591649619266595911992489425412191)
* (apply #'logxor *)
7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777

2

Python 2, 103 + 42 = 145 byte

Python supporta nativamente i bigints, ma questo programma supera di gran lunga i 20 secondi per un numero di 100 cifre. Tuttavia, si decompone numeri interi a 64 bit in circa 2 secondi.

from random import *
def d(a):
 b=c=0
 while set(`b`+`c`)&set('037'):
    b=randint(1,a);c=a^b
 return b,c

1
Idea intelligente usando casualità. Se stai definendo una funzione, non hai bisogno di un whileciclo per continuare a provare valori casuali: puoi semplicemente chiamare di nuovo la funzione. Senza necessità di struttura di controllo, è possibile comprimere la funzione per un lambdae un ternario: from random import* d=lambda a,b=0:set(`b`+`a^b`)&set(\'037\')and d(a,randint(1,a))or(b,a^b). Anche se potresti stare meglio semplicemente non usando una funzione.
xnor

Ho considerato la ricorsione, ma provoca un overflow dello stack per grandi numeri (anche solo 11 cifre).
Remy,

1

Python 3 (132 byte)

(Questo è solo per stimolare soluzioni migliori. Questa è la mia soluzione per risolvere il problema originale nel film ASCII.)

def d(a):
 l=len(str(a));s=int('1'*l);u=10**(l-1)
 while u:
  while set(str(s)+str((a^s)//u))&set('037'):s+=u
  u//=10
 print(s,a^s)

Sebbene il comportamento di xor bit per bit nel sistema decimale sia piuttosto complicato, vi è un'osservazione importante: la modifica delle cifre basse non influirà sulle cifre alte . Pertanto, possiamo lavorare dall'alto verso il basso: prova a rendere le cifre superiori libere da 0, 3, 7 e quindi lavora alla cifra successiva, fino a quando non viene elaborato l'intero numero. Questo ci consente di eseguire in tempo lineare, quindi l'elaborazione di un numero di mille cifre può essere completata in meno di 1 secondo. (Anche la soluzione Common Lisp sta usando la stessa tecnica che credo.)


Ma fissare cifre basse può influire sulle cifre alte. Per esempio, 997^8 == 1005. Penso che ci sia un nocciolo di un'idea qui, ma non è ovvio.
Keith Randall,

@KeithRandall: Sì, è proprio come 999 ... 999 + 1, ma, data la scelta {1,2,4,5,6,8,9}, ce ne sarebbero alcuni che non influiranno sulle cifre alte. (ad es 997^2 == 999.). Il whileciclo interno fa l'esaurimento per trovare la scelta che mantiene valide le cifre alte.
kennytm,

giusto, ma poi non è ovvio (almeno per me) che ci sia sicuramente una cifra che funzionerà.
Keith Randall,
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.