Numeri del fucile da caccia


45

I numeri del fucile sono una sequenza con una definizione piuttosto semplice ma con una struttura interessante. Inizia con i numeri naturali:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

Ora prendi tutti i numeri in indici divisibili per 2 , raggruppali in coppie e scambia i numeri in ciascuna coppia:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...
   ^     ^     ^     ^      ^       ^       ^  
    <--->       <--->        <----->         <----
1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...

Ora fai lo stesso con gli indici divisibili per 3 :

1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...
      ^        ^        ^           ^          
       <------>          <--------->           
1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...

E poi per 4 , 5 , 6 e così via:

1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...
1, 4, 8, 6, 5, 3, 7, 2, 10, 12, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 3, 7, 2, 10, 5, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 14, 7, 2, 10, 5, 11, 3, 13, 16, ...
...

Dopo k tali passaggi, verranno fissati i primi k + 1 numeri. Quindi possiamo definire la sequenza infinita di numeri di Fucile a pompa come limite per lasciare k all'infinito. I primi 66 numeri sono:

1, 4, 8, 6, 12, 14, 16, 9, 18, 20, 24, 26, 28, 22, 39, 15, 36, 35, 40, 38, 57, 34, 48, 49, 51, 44,
46, 33, 60, 77, 64, 32, 75, 56, 81, 68, 76, 58, 100, 55, 84, 111, 88, 62, 125, 70, 96, 91, 98, 95,
134, 72, 108, 82, 141, 80, 140, 92, 120, 156, 124, 94, 121, 52, 152, 145, ...

Curiosità: nonostante sia ottenuto solo permutando i numeri naturali, questa sequenza non contiene numeri primi.

La sfida

Dato un numero intero n > 0, trova il nnumero del fucile. È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e restituendo l'output o stampandolo su STDOUT (o l'alternativa più vicina).

Questo è il golf del codice, quindi vince l'invio più breve (in byte).

Classifiche

Questo sta ottenendo più risposte di quanto pensassi, oltre a diverse persone che competono nella stessa lingua. Quindi ecco uno snippet di stack per generare sia una classifica regolare che una panoramica dei vincitori per lingua.

Per assicurarti che la tua risposta venga visualizzata, ti preghiamo di iniziare la risposta con un titolo, usando il seguente modello Markdown:

# Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
Quel fatto divertente è folle, questo algoritmo mescola tutti i numeri primi fino alla fine? Oppure ci sono altri numeri naturali che non si verificheranno?
Devon Parsons,

1
@DevonParsons Sì, mescola tutti i numeri primi "fino alla fine". Ma penso che manchino anche altri numeri. Sembra che 10, 21, 25e 30non compaiono né, per esempio.
Martin Ender,

3
Sembra una domanda di Project Euler. Non penso che sia ... ma forse dovrebbe essere.
Corey Ogburn

9
In generale, alla kiterazione, l' kelemento th nell'array viene trasposto nella 2kposizione th, e non viene toccato di nuovo fino alla 2kiterazione, momento in cui viene trasposto nella 4kposizione th, all'infinito. Un numero primo non viene trasposto fino a quando non arriva il suo turno, per così dire, quindi tutti i numeri primi vengono spostati in avanti. Ma possiamo facilmente fare un elenco delle vittime innocenti semplicemente stampando il primo elemento da trasporre all'iterazione 2 e ad ogni iterazione dispari. L'elenco è: 2, 3, 5, 7, 10, 11, 13, 21, 17, 19, 30, 23, 27, 25, 29, 31, 45, 42, 37, 54, 41, 43, 65, ...
Théophile,

3
@ Sherlock9 Fatto! Se approvato, sarà https://oeis.org/A266679 . Felice anno nuovo!
Théophile il

Risposte:


5

Pyth, 19 22

u-G*H^_!%GH/GHrhQ2Q

Un'implementazione abbastanza ingenua della risposta di golfscript di @ PeterTaylor .

Provalo online qui

Questo usa gli stessi trucchi per convertire un ciclo while in una piega come fa l'altro programma Pyth qui sotto.


u+G**H!%GHty%/GH2rhQ2Q

Una copia ingenua dell'algoritmo di @ Sp3000 tradotto in Pyth.

Puoi provarlo online qui

Usa la riduzione (nome di Python per piega) per emulare il ciclo while. Enumera su range(input, 2)quale in Pyth risolve range(2, input)[::-1]. Gli altri campi da golf relativi a Pyth implicano l'uso notanziché <2e l'utilizzo ydella modalità nascosta per raddoppiare il valore degli argomenti numerici.


21

> <>, 52 45 byte

Pagina Esolangs per> <>

i:&&:&1-?vn;
2*1-*+20.>:&:&%1(&:&*{:}&:1-&,2%

Ci sono molti elementi di copia e spostamento in giro, grazie ai numerosi moduli e alle moltiplicazioni necessarie. La logica è esattamente la stessa della mia soluzione Python .

Riceve input tramite un punto di codice da STDIN, ad es "!" = 33 -> 75.


10
E hai ottenuto il premio per il formato di input più imbarazzante di sempre: P
Caridorc

+1 comunque, non ti preoccupare :)
Caridorc

@ Sp3000 IMO dovrebbe contare solo come uno
SuperJedi224

@ SuperJedi224 In realtà, secondo questo meta post apparentemente -vconta come tre: /
Sp3000

17

Python 2, 58 byte

i=n=input()
while~-i:n+=(n%i<1)*i*(n/i%2*2-1);i-=1
print n

Come la maggior parte delle altre risposte, l'idea è di lavorare all'indietro.


Chiamiamo step k+1step i, in modo che al step itutti i multipli di ivengano scambiati. Abbiamo bisogno di due semplici osservazioni:

  • La posizione nnell'array viene scambiata al passaggio solo ise nè divisibile per i,
  • Per sapere se sei il numero più basso o il numero più alto nello scambio, guarda n/i mod 2. Se questo è 1 sei il numero più basso (e cambierà in alto), altrimenti sei il numero più alto (e cambierà in basso).

Questo ci dà un algoritmo per lavorare all'indietro. Proviamo con 6, a partire dall'ultimo passaggio (passaggio i = 6):

Step 6: Position 6 swaps with position 12 (6 is divisible by 6, 6/6 = 1 == 1 mod 2)

Quindi ora sappiamo che il numero proviene dalla posizione 12. Quindi:

Step 5: No swap (12 not divisible by 5)
Step 4: Position 12 swaps with position 16 (12 is divisible by 4, 12/4 = 3 == 1 mod 2)

Quindi ora sappiamo che è arrivato da 16 prima. Finalmente:

Step 3: No swap (16 not divisible by 3)
Step 2: Position 16 swaps with position 14 (16 divisible by 2, 16/2 = 8 == 0 mod 2)

Dato che questo è il primo passo (ricorda, k+1), abbiamo finito e il numero che finisce nella posizione 6 originariamente proveniva dalla posizione 14, cioè il sesto numero di fucile è 14.

Quindi ora per la spiegazione di Python:

i=n=input()             Read input, and store into i (step) and n (position)
while~-i:               while i-1 != 0:, or since we're descending with i this is just while i>1:
  n+=                   Add to the current position...
    (n%i<1)*            1* whatever's next if n is divisible by i, otherwise 0* (i.e. nothing)
    i*                  How many positions n might go up/down
    (n/i%2*2-1)         n/i%2 tell us higher/lower, *2-1 maps 0 or 1 to -1 (down) or +1 (up)
  i-=1                  Decrement the step number
print n                 Output

modo interessante di scrivere i-1come~-i
mbomb007

6
@ mbomb007: concordato. Intelligente però, poiché ha lo stesso significato ma elimina la necessità di uno spazio dopo while. Bel lavoro, Sp3000.
Alex A.

Il più breve che ho potuto ottenere in Pyth è stato utilizzando u+G**H!%GHty%/GH2rhQ2Q
Riduci

1
@FryAmTheEggman, Sp3000, nessuno di voi lo pubblicherà?
Martin Ender,

@ MartinBüttner All'inizio non l'avevo postato perché pensavo fosse troppo una copia. Lo pubblicherò come risposta in CW per ora.
FryAmTheEggman

6

Haskell, 68 byte

n#k|mod k(2*n)<1=k-n|mod k n<1=k+n|k>0=k
s n=foldr((.).(#))id[2..n]n

Probabilmente più golfabile, in particolare la prima fila. Questo definisce una funzione sche accetta ne restituisce il nnumero del fucile.

map s [1..66]
[1,4,8,6,12,14,16,9,18,20,24,26,28,22,39,15,36,35,40,38,57,34,48,49,51,44,46,33,60,77,64,32,75,56,81,68,76,58,100,55,84,111,88,62,125,70,96,91,98,95,134,72,108,82,141,80,140,92,120,156,124,94,121,52,152,145]

Spiegazione

La funzione helper #accetta due numeri ne k, e restituisce il knumero th nella lista definito applicando l'operazione di scambio di coppia ad ogni nnumero th. Ad esempio, applicandolo ai primi 20 numeri con si n = 4ottiene questo:

map (4#) [1..20]
[1,2,3,8,5,6,7,4,9,10,11,16,13,14,15,12,17,18,19,24]

Il risultato di s nsi ottiene riducendo ("piegando") l'elenco [2..n]con la funzione del secondo ordine (.).(#), che accetta un numero me una funzione f(inizialmente la funzione identità id) e restituisce una funzione che accetta ke restituisce f (m # k). Ad esempio, nel caso in cui n = 4l'elenco [2,3,4]venga ridotto a una funzione che accetta ke restituisce id (4 # (3 # (2 # k))). È idnecessario solo per il caso base n = 1, in cui l'elenco è vuoto. Infine, diamo a questa funzione l'ingresso k = n, ottenendo il nnumero del fucile.


6

CJam, 32 byte

Basta seguire le specifiche al punto. Esecuzione delle istruzioni su un set più grande in modo da non influenzare l' ennesimo numero.

ri:N)2#,:)N{))/2/{:)~\@}%:+}/N(=

Provalo online qui


5

Rubino, 92 byte

def s(d,n)
d==1?n:s(d-1,n%d==0?n+(n%(d*2)==0?-d :d):n)
end
n=ARGV[0].to_i
print s(n,n).to_s

Il mio primo sforzo per il golf del codice. Non basato su altre risposte.


Ora che ho visto alcuni degli altri, noto che la maggior parte definisce una funzione, non un programma completo che accetta input e produce output. L'OP ha richiesto un programma completo con input e output. È consuetudine ignorare tali requisiti?


84 byte

n=ARGV[0].to_i
d=n
while d>1
n+=(n%d==0?(n%(d*2)==0?-d :d):0)
d-=1
end
print n.to_s

Dopo aver esaminato altre risposte e aver realizzato che è possibile una soluzione iterativa.


2
Alcuni miglioramenti per la tua soluzione a 84 byte: 1. Passa ARGVal $*magico mondo. 2. Non to_sè necessario. 3. Invece di assegnare da nsu una linea separata, basta fare la d=n=...barba di un personaggio. Bel lavoro per il tuo primo golf! :)
Maniglia della porta

1
Dove sto chiedendo un programma completo? "Puoi scrivere un programma o una funzione ...";) (Questo è anche il valore predefinito per le sfide del code-golf , ma di solito lo includo per completezza.)
Martin Ender

Per aggiungere ai suggerimenti di @ Doorknob, due serie di parentesi sulla n+=riga non sono necessarie ed entrambe le occorrenze ==0possono essere modificate in modo sicuro <1.
Peter Taylor,

5

Python 2, 97 79 caratteri

g=lambda n,k:n>1and g(n-1,k-(k%n<1)*n*(-1)**(k/n%2))or k
n=input()
print g(n,n)

Determina per ciascun indice il valore corretto inseguendo ricorsivamente il numero all'indietro. L'algoritmo è stato scoperto in modo indipendente.

modifica: ora stampa solo il nnumero th anziché i primi nnumeri. Ovviamente un approccio iterativo sarebbe più breve, ma non voglio copiare il codice di Sp3000.


Sì, penso che tutti convergeranno su questo. Ho trovato la g(i,i)parte particolarmente fastidiosa però ...
Sp3000

2
La lingua dovrebbe essere contrassegnata come Python 2, a causa printdell'istruzione.
mbomb007,

@ mbomb007 Corretto.
Jakube

4

Haskell, 79 byte

1#i=i
s#i|i`mod`(2*s)==0=(s-1)#(i-s)|i`mod`s==0=(s-1)#(i+s)|1<2=(s-1)#i
p n=n#n

Utilizzo: p 66quali output145

Non c'è molto da spiegare: la funzione #calcola ricorsivamente il numero del fucile nella posizione idel passo s. p nrestituisce il numero nella posizione ndel passaggio n.


Oh, non ho visto la tua risposta prima di inviare la mia. Sembra che abbiamo approcci piuttosto diversi.
Zgarb,

4

k, 41 byte

{{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}

 / apply to an int
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]} 42
111
 / apply to 1 through 66
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}'1+!66
1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44 46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95 134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145
  • {...} lambda, xey sono l'argomento implicito 1o e 2o
  • $[b;t;f] operatore ternario, valuta b seguito rispettivamente da t / f
  • b!a a modulo b
  • _ piano, lancia il risultato della divisione in un int
  • % divisione
  • {...}/[x;y] prime {...} con x e si applicano sull'elenco y, equivale a f [f [.. f [f [x; y0]; y1]; .. yn-1]; yn]
  • | inverso
  • ! funzione iota, genera l'elenco da 0 a n-1

4

Lisp comune, 113 91

(iterativo: 91)

(defun s(n)(do((r n(1- r)))((= r 1)n)(if(= 0(mod n r))(incf n(* r(if(oddp(/ n r))1 -1))))))

(originale, ricorsivo: 113)

(defun s(n &optional(r n))(cond((= r 1)n)((= 0(mod n r))(s(+ n(* r(if(oddp(/ n r))1 -1)))(1- r)))(t(s n(1- r)))))

Esempio

Con la versione ricorsiva:

(trace s)
(s 10)

  0: (S 10)
    1: (S 20 9)
      2: (S 20 8)
        3: (S 20 7)
          4: (S 20 6)
            5: (S 20 5)
              6: (S 15 4)
                7: (S 15 3)
                  8: (S 18 2)
                    9: (S 20 1)
                    9: S returned 20
         ...
    1: S returned 20
  0: S returned 20

test

Controlli e misure per la versione iterativa:

(let ((list '(1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44
              46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95
              134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145)))
  (time
   (loop for r in list
         for n from 1
         always (= r (s n)))))

 => T

Evaluation took:
  0.000 seconds of real time
  0.000000 seconds of total run time (0.000000 user, 0.000000 system)
  100.00% CPU
  807,160 processor cycles
  32,768 bytes consed

4

Mathematica, 53 49 byte

(For[i=n=#,n>1,--n,If[n∣i,i+=Mod[i,2n]2-n]];i)&

Ho deciso di golf la mia implementazione di riferimento. Il è il simbolo Unicode per "divide", e conta per 3 byte. In caso contrario, utilizza lo stesso algoritmo di tutti gli altri.

Definisce una funzione senza nome che accetta ncome singolo parametro e restituisce il nnumero del fucile.


4

GolfScript, 27 caratteri

~.,(~%{):i\.@%!~)1$i/?i*-}/

Spiegazione

Se f(i, n)è il valore in posizione ndopo le i-1trasformazioni, abbiamo

f(1, n) = n
f(i, n) = f(i - 1, n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n)  for i > 1

dove ^denota xor bit a bit; dato input n, vogliamo calcolare f(n, n).

La conversione da una funzione ricorsiva a un ciclo non è interessante; ciò che è interessante è il modo in cui

n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n

può essere riscritto. L'approccio più ovvio è dire che deve essere

n + (n % i == 0 ? i : 0) * g(n / i)

per alcuni g. Ovviamente si galterna tra 1e -1, man mano che le posizioni si alternano su e giù; poiché g(1) = 1(perché si 1scambia fino a 2), abbiamo

n + (n % i == 0 ? i : 0) * -1**(1 + n / i)

dove **indica esponenziazione. Il risparmio finale deriva dalla riscrittura di questo

n - i * (n % i == 0 ? -1 : 0)**(n / i)

Dissezione

~             # Evaluate input to get n
.,(~%{        # For n-1 downto 1...
  ):i         #   Let i be that value + 1, so for i = n downto 2...
  \.@%!       #   Find n % i == 0 ? 1 : 0
  ~)          #   Negate
  1$i/?       #   Raise to the power of n/i
  i*-         #   Multiply by i and subtract
}/

Visto che hai le risposte GS e CJam più brevi, perché non hai anche le risposte Pyth più brevi? u-G*H^_!%GH/GHrhQ2QSe non vuoi pubblicarlo tu stesso, dimmelo / aggiungilo alla risposta CW.
FryAmTheEggman,

@FryAmTheEggman, potrei non essere molto praticato in CJam, ma posso almeno leggerlo più o meno. Non ho idea di cosa dice il Pyth nel tuo commento, anche se dal contesto presumo sia una porta di questa risposta. Quindi è meglio che lo pubblichi, perché puoi rispondere a domande a riguardo.
Peter Taylor,


4

Julia, 61 57 byte

n->(i=n;while~-i!=0 n+=(n%i<1)*i*(n÷i%2*2-1);i-=1;end;n)

Questo crea una funzione senza nome che prende un singolo argomento ne restituisce il nnumero di fucile esimo. Per chiamarlo, dagli un nome, ad es f=n->(...).

Esempi:

julia> for i = 1:10 println(f(i)) end
1
4
8
6
12
14
16
9
18
20

Attualmente si basa sulla fantastica risposta Python di @ Sp3000 . Lo rivedrò presto perché a Julia ci deve essere un modo più breve di farlo rispetto a quello che ho fatto qui. Qualsiasi input è il benvenuto, come sempre.



3

CJam, 28 27 byte

Quindi questo è leggermente imbarazzante ... prima di pubblicare questo, ho provato a giocare a golf da solo e sono arrivato a 30 byte in CJam. Nessuna delle risposte esistenti lo ha ancora battuto. Nel frattempo sono anche riuscito a radere altri tre byte. V'è una soluzione Pyth più corto in un commento, ma nulla più breve è stata pubblicata in una risposta, ecco che è. Forse ispira le persone APL / J a provare un po 'di più (o qualcuno in realtà pubblica la soluzione Pyth), prima che io debba accettare la mia risposta. ;)

l~__(,f-{_I_+%_+I-_zI=*+}fI

Provalo qui.

Spiegazione

l~                          "Read input N and eval.";
  __(,                      "Duplicate twice, create range [0 1 2 ... N-2].";
      f-                    "Subtract each from N, giving [N N-1 N-2 ... 2].";
        {               }fI "For each element, storing the element in I.";
         _I_+%_+I-          "Compute 2(N % 2I)-I - the shuffling offset";
                  _zI=      "Check that this offset is ±I.";
                      *+    "Multiply the offset by this boolean and update to N.";

3

J, 34 32 byte

   (]+[*(1-~2*2|%~)*0=|)/@(_1}2+i.)

   ((]+[*(1-~2*2|%~)*0=|)/@(_1}2+i.)) every 1+i.20  NB. running with inputs 1..20
1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38

Proverò a giocare un po 'di più e aggiungerò qualche spiegazione in seguito.

Provalo online qui.



1

Rubino, 57 47 byte

Questo è essenzialmente SP3000 soluzione pitone s'(con suggerimento di XNOR ) tradotto a rubino. Probabilmente potrei giocare a golf in alcuni punti però.

->n{n.downto(2).map{|i|n+=i*(n/i%2-~-n/i%2)};n}
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.