Dividi, dividi e conquista


22

A volte, quando sto pigramente cercando di calcolare il numero che appare davanti a me¹, dopo un po 'mi rendo conto che è più facile di quanto pensassi. Prendiamo 2156ad esempio: alla fine mi viene in mente che entrambi 21e 56sono multipli di 7, e quindi sicuramente 2156 = 21 x 100 + 56è anche un multiplo di 7.

Il tuo compito è scrivere del codice che identifichi i numeri che sono più facili da considerare a causa di una coincidenza di questo tipo.

Più precisamente:

Scrivi un programma o una funzione che accetta un intero positivo ncome input e restituisce un valore di verità se esiste un divisore d(maggiore di 1) tale che npuò essere tagliato in due per produrre due numeri interi positivi, ognuno dei quali è un multiplo di d; restituire un valore errato in caso contrario.

  • "Troncato in due" significa ciò che pensi: la solita rappresentazione in base 10 di npartizionata ad un certo punto in una metà anteriore e una metà posteriore per produrre altri due numeri interi in base 10. Va bene se il secondo numero intero ha uno zero iniziale (ma nota che deve essere un numero intero positivo, quindi la divisione 1230in 123e 0non è valida).
  • I valori di verità e falsità possono dipendere dall'input. Ad esempio, se un numero intero diverso da zero è veritiero nella tua lingua di scelta, allora sei il benvenuto a restituire il divisore do uno dei "pezzi" di n(o nse stesso per quella materia).
  • Ad esempio, qualsiasi numero pari con almeno due cifre nell'insieme {2, 4, 6, 8}produrrà un valore veritiero: basta dividerlo dopo la prima cifra pari. Ad esempio, qualsiasi numero primo nprodurrà un valore falso, così come qualsiasi numero a una cifra.
  • Si noti che è sufficiente considerare i divisori primi d.
  • È possibile supporre che l'input sia valido (ovvero un numero intero positivo).

Questo è , quindi vince il codice più breve in byte. Ma le soluzioni in tutte le lingue sono benvenute, quindi possiamo cercare il codice più breve in ogni lingua, non solo il codice più breve in generale.

Casi test

(Devi solo generare un valore di verità o falsa; le annotazioni di seguito sono solo a scopo di spiegazione.) Alcuni input che danno valori di verità sono:

39  (3 divides both 3 and 9)
64  (2 divides both 6 and 4)
497  (7 divides both 49 and 7)
990  (splitting into 99 and 0 is invalid; but 9 divides both 9 and 90)
2233  (11 divides both 22 and 33)
9156  (3 divides both 9 and 156; or, 7 divides both 91 and 56)
11791  (13 divides both 117 and 91)
91015  (5 divides both 910 and 15)
1912496621  (23 divides both 1912496 and 621; some splittings are multiples of 7 as well)
9372679892  (2473 divides both 937267 and 9892; some splittings are multiples of 2 as well)

Alcuni input che producono valori falsi sono:

52
61
130  (note that 13 and 0 is not a valid splitting)
691
899
2397
9029
26315
77300  (neither 7730 and 0 nor 773 and 00 are valid splittings)
2242593803

¹ sì, lo faccio davvero

Risposte:


7

Retina , 31 29 byte


,$';$`
\d+
$*
;(11+)\1*,\1+;

Provalo online!

Emette un numero intero positivo per input validi e zero per quelli non validi.

Non consiglierei di aspettare i casi di test più grandi ...

Spiegazione


,$';$`

Ad ogni posizione dell'input inserire una virgola, quindi tutto prima di quella posizione, quindi un punto e virgola, quindi tutto dopo questa posizione. Che cosa fa? Ci dà tutte le possibili divisioni di un numero (diviso per ,, separato da ;), e quindi di nuovo l'input alla fine. Quindi l'input 123diventa

,123;1,23;12,3;123,;123
     ^     ^     ^

dove ho contrassegnato i caratteri di input originali (l'elemento che non è contrassegnato è ciò che abbiamo inserito). Si noti che ciò crea suddivisioni non valide che non sono effettive suddivisioni e inoltre non importa se il componente finale è tutto zero, ma eviteremo di accettarli in seguito. Il vantaggio di creare divisioni non valide è che sappiamo che ogni suddivisione valida ha un ;fronte e uno dopo, quindi possiamo salvare due byte sui confini delle parole.

\d+
$*

Converti ogni numero in unario.

;(11+)\1*,\1+;

Abbina una divisione abbinando entrambe le metà come multipli di un numero che è almeno 2.


Domanda veloce su Retina: cosa fa la newline leader?
HyperNeutrino,

@HyperNeutrino Bene, la prima riga è la prima regex che abbiniamo e vogliamo abbinare la regex vuota, al fine di inserire la sostituzione in ogni singola posizione tra i caratteri.
Martin Ender,

Oh ok. Grazie! Probabilmente dovrei guardare un po 'di più Retina; poiché sembra ampiamente basato su regex, potrebbe essere utile per problemi di complessità di kolmogorov .
HyperNeutrino,

L'ultima riga potrebbe essere;(11+)+,\1+;
Riley il

@Riley che non garantisce che il primo segmento sia un multiplo dello stesso fattore.
Martin Ender,

6

Brachylog (2), 8 byte

~c₂ḋᵐ∋ᵐ=

Provalo online!

Spiegazione

~c₂ḋᵐ∋ᵐ=
~c₂       Split the input into two pieces
    ᵐ ᵐ   On each of those pieces:
   ḋ ∋      Choose a prime factor
       =  such that both the chosen factors are equal

Chiaramente, se lo stesso numero (maggiore di 1) divide entrambi i pezzi, lo stesso numero primo li dividerà entrambi. Se si richiede che il fattore sia primo, non è consentito 1 come fattore. Inoltre impedisce che un letterale 0venga scelto come un segmento di un numero (perché 0non ha una fattorizzazione primaria e causerà un fallimento).

Non è necessario verificare la corrispondenza con gli zero interni corrispondenti; se una scissione xed 0yè valido, x0e yfunziona altrettanto bene (e in senso contrario, se x0e yopere, allora abbiamo una soluzione di lavoro indipendentemente dal fatto xe 0yavrebbe funzionato o meno).

Un programma completo di Brachylog, come questo, restituisce un valore booleano; true.se esiste un modo per eseguirlo senza errori (ovvero per fare scelte in modo tale che non si verifichino errori), false.se tutti i percorsi portano al fallimento. Questo è esattamente ciò che vogliamo qui.


4

Gelatina , 14 12 11 10 byte

ŒṖḌo1g/€P>

Grazie a @JonathanAllan per il golf off 1 byte!

Provalo online!

Come funziona

ŒṖḌo1g/€P>  Main link. Argument: n

ŒṖ          Compute all partitions of n's decimal digits.
  Ḍ         Undecimal; convert each array in each partition back to integer.
   o1       OR 1; replace disallowed zeroes with ones.
     g/€    Reduce (/) each (€) partition by GCD (g).
            The last GCD corresponds to the singleton partition and will always be
            equal to n. For a falsy input, all other GCDs will be 1.
        P   Take the product of all GCDs.
         >  Compare the product with n.

Penso che puoi rilasciare D, come make_digitsè in vigore per ŒṖ.
Jonathan Allan,

Per qualche ragione, ho pensato che avrebbe creato un intervallo ... Grazie!
Dennis,

3

Mathematica, 63 62 byte

(1 byte grazie a Greg Martin)

1<Max@@GCD@@@Table[1~Max~#&/@Floor@{Mod[#,t=10^n],#/t},{n,#}]&

È una funzione che accetta un numero intero come input e restituisce Trueo False. Se lo provi su un numero elevato, porta un libro da leggere mentre aspetti.

Spiegazione:

  • Floor@{Mod[#,t=10^n],#/t}divide aritmeticamente l'input nelle ultime ncifre e nelle m-ncifre rimanenti (dove mè il numero totale di cifre).
  • Table[1~Max~#&/@...,{n,#}]fa questo per ogni nfino al numero di input. (Questo è troppo grande. Dobbiamo solo farlo fino al numero di cifre dell'input, ma in questo modo salva byte e dà comunque il risultato corretto.) Il 1~Max~#&/@bit elimina gli zero, quindi numeri come 130 -> {13,0}non contano come True.
  • 1<Max@@GCD@@@... trova il massimo comune divisore di ciascuna di queste coppie e verifica se qualcuno di questi divisori è maggiore di 1. In caso affermativo, abbiamo trovato il modo di fattorizzare il numero suddividendolo.

1
Bella risposta! È possibile salvare un byte con {#~Mod~10^n,#/10^n}o {Mod[#,t=10^n],#/t}.
Greg Martin,

Ho provato #~Mod~10^n, ma sembra essere racchiuso tra parentesi come Mod[#,10]^ninvece di Mod[#,10^n]. Non ho pensato al tuo secondo suggerimento, però!
Non un albero il

punto giusto suMod[#,10]^n
Greg Martin


2

C, 145 142 139 138 135 byte

i,a,b;f(){char s[99];scanf("%s",s);for(char*p=s;*p++;)for(b=atoi(p),i=*p,*p=0,a=atoi(s),*p=i,i=1;i++<b;)*s=a%i-b%i|b%i?*s:0;return!*s;}

2

JavaScript (ES6), 74 71 70 byte

f=(s,t='',u)=>u?s%t?f(t,s%t,1):t:s&&f(t+=s[0],s=s.slice(1),1)>1|f(s,t)
<input oninput=o.textContent=f(this.value)><span id=o>

Accetta l'input come una stringa, utile per lo snippet. Modifica: salvato 3 byte grazie a @ user81655.


Salva due byte: (c,i)-> c, i+1-> ++i, t=''-> i=t='', questo trucco è utile in qualsiasi momento è necessario utilizzare gli indici 1-based e avere un posto per inizializzare ia 0.
user81655

Anche io credo che t=''potrebbe essere t=0, dal momento che l'aggiunta lo ccostringe a una stringa comunque.
user81655

@ user81655 Questo è accaduto perché inizialmente ho diviso da e verso i, quindi non avevo bisogno di indici basati su 1, ma poi ho golfato la prima fetta t+=c.
Neil

Ah ok. Anche un'ultima cosa, credo che questo potrebbe anche essere più breve come una funzione ricorsiva: f=(x,y,z)=>z?x%y?g(y,x%y):y:x?f(x,y,1)>1||f(x.slice(1),~~y+x[0]):0. Ho combinato anche la tua funzione GCD f. Probabilmente potrebbe essere ulteriormente giocato a golf. Ultimo suggerimento, lo prometto! : P
user81655

@ user81655 Purtroppo la mia gcdfunzione semplificata non funziona quando x=0, e aggirando questo e il tuo errore di battitura mi ha portato a 72 byte, quindi è stato fortunato che sono stato in grado di golf via 2 byte.
Neil,

2

Python 3, 133 118 117 byte

i,j=int,input()
from fractions import*
print(any(i(j[k:])*i(j[:k])*~-gcd(i(j[k:]),i(j[:k]))for k in range(1,len(j))))

Certamente non il più breve, probabilmente potrebbe essere abbreviato un po '. Funziona in O(n)tempo. L'input è in formato \d+e l'output è in formato (True|False)come da valore booleano predefinito Python
-3 byte grazie a Dead Possum
-15 byte grazie a ovs
-1 byte grazie a This Guy


from fractions import*risparmierebbe 3 byte
Dead Possum il

Restituisce True per 900. Immagino che sia sbagliato. Mb dovresti cambiare interno anya all? In tal caso, è possibile modificare tutta quella parte per i(j[k:])and i(j[:k])portarla a 125 byte. Ecco alcune correzioni
Dead Possum,

Puoi sostituire e e tutti moltiplicando:any(i(j[k:])*i(j[:k])*~-gcd(i(j[k:]),i(j[:k]))for k in range(1,len(j)))
ovs

@DeadPossum Oh giusto, avrei dovuto farlo. E sì, il mio metodo attuale ha molte parti golfabili, ma seguirò i suggerimenti di ovs. Grazie per la segnalazione! (avrei dovuto testarlo da solo ... vabbè ...)
HyperNeutrino,

È possibile rimuovere un byte (quasi nulla) rimuovendo lo spazio tra)) for
caird coinheringaahing

1

QBIC , 91 90 byte

;_LA|[a-1|B=left$(A,b)┘C=right$(A,a-b)┘x=!B!┘y=!C![2,x|~(x>1)*(y>1)*(x%c=0)*(y%c=0)|_Xq}?0

Spiegazione:

;               Get A$ from the command prompt
_LA|            Get the length of A$ and place it in a% (num var)
[a-1|           for b%=1; b% <= a%-1; b%++
B=left$(A,b)    break A$ in two components on index b%
C=right$(A,a-b)
x=!B!┘y=!C!     Convert both parts from string to num, assign to x% and y%
[2,x|           FOR c% = 2; c% <= x%; c%++

This next IF (~ in QBIC) is a bit ... iffy. It consists of a set of comparators.
Each comparator yields a -1 or a 0. We take the product of these. At any failed
comparison this will yield 0. When successful, it yields 1, which is seen as true by QBasic.

~(x>1)*(y>1)        IF X>1 and Y>1 --> this stops '00' and '1' splits.
*(x%c=0)*(y%c=0)    Trial divide the splits on loop counter c%.

|_Xq            Success? THEN END, and PRINT q (which is set to 1 in QBIC)
}               Close all language constructs (2 FOR loops and an IF)
?0              We didn't quit on match, so print 0


1

Perl 5 , 46 byte

43 byte di codice + 3 byte per -pflag.

s~~$\|=grep!($`%$_|$'%$_),2..$`if$`*$'~ge}{

Provalo online! oppure prova questa versione modificata che consente più input.
Probabilmente non vorrai provare questo sull'input più grande, poiché potrebbe richiedere del tempo (molto lungo).

Spiegazioni:
Esaminiamo ogni posizione nella parola con s~~~g, con il $`contenimento dei numeri prima e $'dei numeri dopo. Se $`*$'è vero (significa che nessuno è vuoto e nessuno lo è 0), quindi controlliamo se un numero tra 2 e li $`divide entrambi (con il grep!(...),2..$`). In tal caso, $\|=..verrà impostato $\un valore diverso da zero, che viene implicitamente stampato alla fine grazie al -pflag.


2
Se qualcuno sa come rendere un $<backquote>markdown in SE, ti sarei grato se mi dicessi come.
Dada,

1
Puoi farlo usando esplicitamente <code>... </code>(piuttosto che `... `), quindi sfuggendo ai backquotes come \`. Inoltre, questo commento è stato un dolore da scrivere, perché deve essere evaso due volte (e le due serie di regole di fuga sono diverse!).

@ ais523 Fantastico, grazie mille! :)
Dada,

0

Python 2 , 69 byte

f=lambda n,d=10,k=2:k<d<n and(n/d%k+n%d%k<1<n%d)|f(n,d,k+1)|f(n,10*d)

Utilizza la ricorsione al posto dei built-in GCD.

Provalo online!

Come funziona

Quando f viene chiamato con uno a tre argomenti ( d default a 10 , k a 2 ), controlla prima il valore dell'espressione k<d<n. Se le disuguaglianze k <d e d <n sono entrambe valide, l'espressione seguente andviene eseguita e il suo valore viene restituito; in caso contrario, f restituirà semplicemente False .

Nel primo caso, iniziamo valutando l'espressione n/d%k+n%d%k<1<n%d.

d sarà sempre una potenza di dieci, così n/ded n%defficacemente dividere le cifre decimali di n in due fette. Queste sezioni sono entrambe divisibili per k se e solo se n/d%k+n%d%krestituiscono 0 , che viene testato confrontando il risultato con 1 .

Poiché parte dei requisiti è che entrambe le sezioni devono rappresentare numeri interi positivi, anche il valore di n%dviene confrontato con 1 . Si noti che 1 non ha divisori primi, quindi non è richiesto il confronto più costoso con 0 . Inoltre, nota che d <n garantisce già che n/dvaluterà un numero intero positivo.

Alla fine ricorsivamente tutto f(n,d,k+1)(provando il prossimo potenziale divisore comune) e f(n,10*d)(provando a dividere) e restituisce l'OR logico di tutti e tre i risultati. Ciò significa che f restituirà True se (e solo se) k è un divisore comune di n / d e n% d o lo stesso vale per un valore maggiore di k e / o una potenza maggiore di dieci d .

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.