Ordina per Moltiplicare


34

Dovresti scrivere un programma o una funzione che, dato un elenco di numeri interi positivi, moltiplica ogni elemento con il numero intero positivo più piccolo possibile per creare un elenco strettamente crescente.

Ad esempio se l'ingresso è

5 4 12 1 3

le moltiplicazioni saranno

5*1=5 4*2=8 12*1=12 1*13=13 3*5=15

e l'output sarà l'elenco crescente

5 8 12 13 15

Ingresso

  • Un elenco di numeri interi positivi contenenti almeno 1 elemento

Produzione

  • Un elenco di numeri interi positivi

Esempi

9 => 9
1 2 => 1 2
2 1 => 2 3
7 3 => 7 9
1 1 1 1 => 1 2 3 4
5 4 12 1 3 => 5 8 12 13 15
3 3 3 8 16 => 3 6 9 16 32
6 5 4 3 2 1 => 6 10 12 15 16 17
9 4 6 6 5 78 12 88 => 9 12 18 24 25 78 84 88
8 9 41 5 12 3 5 6 => 8 9 41 45 48 51 55 60
15 8 12 47 22 15 4 66 72 15 3 4 => 15 16 24 47 66 75 76 132 144 150 153 156

Questo è il codice golf, quindi vince il programma o la funzione più breve.

Curiosità: l'ultimo elemento dell'output per l'ingresso N, N-1, ... ,1sembra essere l' (N+1)thelemento della sequenza A007952 . Se trovi una prova, sei il benvenuto ad includerla nella tua risposta sul golf o pubblicarla come commento.


qualcuno ha ancora messo a punto tale prova?
Connor Clark,

Risposte:


20

Gelatina , 6 5 byte

:‘×µ\

La prima risposta di Jelly prima che @Dennis si svegli e mi picchi. Provalo online!

Spiegazione

:          Integer division, m//n
 ‘         Increment, (m//n+1)
  ×        Multiply, (m//n+1)*n
   µ       Turn the previous links into a new monadic chain
    \      Accumulate on the array

Grazie a @Dennis per -1 byte.


4
:‘×µ\salva un byte.
Dennis,

20
@Dennis Oh merda si è svegliato
Dennis van Gils

9

JavaScript (ES6), 28

Modifica Come suggerito da @Patrick Roberts, ppuò essere un parametro non inizializzato. Stesso numero di byte ma evita di usare una variabile globale

(a,p)=>a.map(n=>p=n*-~(p/n))

TEST

f=(a,p)=>a.map(n=>p=n*-~(p/n))

console.log=x=>O.textContent+=x+'\n'

;[
[[9], [ 9]],
[[1, 2], [ 1, 2]],
[[2, 1], [ 2, 3]],
[[7, 3], [ 7, 9]],
[[1, 1, 1, 1], [ 1, 2, 3, 4]],
[[5, 4, 12, 1, 3], [ 5, 8, 12, 13, 15]],
[[3, 3, 3, 8, 16], [ 3, 6, 9, 16, 32]],
[[6, 5, 4, 3, 2, 1], [ 6, 10, 12, 15, 16, 17]],
[[9, 4, 6, 6, 5, 78, 12, 88], [ 9, 12, 18, 24, 25, 78, 84, 88]],
[[8, 9, 41, 5, 12, 3, 5, 6], [ 8, 9, 41, 45, 48, 51, 55, 60]],
[[15, 8, 12, 47, 22, 15, 4, 66, 72, 15, 3, 4], [ 15, 16, 24, 47, 66, 75, 76, 132, 144, 150, 153, 156]]
].forEach(t=>{
  var i=t[0],k=t[1],r=f(i),ok=(k+'')==(r+'')
  console.log(i + ' => ' + r + (ok?' OK':'FAIL expecting '+x))
})
<pre id=O></pre>


Penso che puoi salvare qualche byte usando il modulo, proprio come ho fatto nella mia risposta .
circa il

Non riesci a saltare p = 0? Ne hai bisogno per eseguirlo su più elenchi, ma la domanda è solo per un singolo elenco
Charlie Wynn,

1
@CharlieWynn se non si inizializza una variabile si ottiene l'errore per una variabile non definita. Se per caso la variabile esiste già (ciò potrebbe facilmente accadere nell'ambiente di una pagina Web), potrebbe avere un valore errato.
edc65,

@ edc65 abbastanza sicuro, p è già definito in questa pagina!
Charlie Wynn,

1
@PatrickRoberts pensando ancora una volta, ho potuto comunque evitare globali: f=a=>a.map(n=>a+=n-a%n,a=0). Ma non è il mio algoritmo (sciocco me) quindi manterrò il mio così com'è e voterò aross
edc65

6

Python 2, 67 64 byte

Prima prova a giocare a golf, quindi i suggerimenti sono apprezzati.

def m(l):
 for x in range(1,len(l)):l[x]*=l[x-1]/l[x]+1
 print l

Ciao, penso che stai contando i ritorni di linea come 2 byte ciascuno (usando Windows?), Ma su questo sito conti ogni ritorno di linea come un singolo byte. Quindi il tuo punteggio è in realtà 65 byte. ( Se non sei sicuro, puoi copiare e incollare il tuo codice in mothereff.in/byte-counter .) Inoltre, puoi fare print linvece di return lsalvare un altro byte. Bel lavoro!
Mathmandan,

Grazie, non sapevo dei ritorni di linea. Questo spiega perché ho sempre avuto conteggi di byte diversi. E non ho nemmeno considerato che la stampa è sufficiente e non deve restituire l'elenco.
Taronyu,

Nessun problema! A proposito, dal momento che hai detto che "i suggerimenti sono apprezzati", potresti essere interessato a navigare attraverso codegolf.stackexchange.com/questions/54/… . Godere!
Mathmandan,

5

PHP, 55 46 42 41 byte

Utilizza la codifica ISO 8859-1.

for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,~ß;

Esegui in questo modo ( -daggiunto solo per l'estetica):

php -d error_reporting=30709 -r 'for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,~ß;' 10 10 8
  • Salvato 1 byte grazie a Ismael Miguel.
  • Salvato 8 byte utilizzando il modulo anziché il piano
  • Salvato 4 byte grazie a Ismael Miguel (per invece di foreach)
  • Hai salvato un byte usando per dare uno spazio.

Penso che puoi sostituirlo $a+0con +$a. Inoltre, puoi presumere che l'ingresso non avrà mai un 0, quindi puoi sostituirlo $a+0&&printcon semplicemente +$a&print. In effetti, potresti persino farlo $a&print, dal momento che in PHP "0" == 0 == 0.0 == false. Ma potrebbe non essere necessario se si utilizza solo un echo, penso.
Ismael Miguel,

Il binario andnon funzionerà (al contrario del logico), né echeggerà in questo modo. Dal momento che sto prendendo input dalla CLI, il primo argomento è -, che voglio catturare invece di stampare uno zero. Prova php -r 'print_r($argv);' foo. Salvato 1 byte con il tuo primo suggerimento, grazie.
circa il

1
Che ne dici for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,' ';? È lungo 42 byte e salta il primo elemento.
Ismael Miguel,

Bello, grazie @IsmaelMiguel
circa il

Prego. Se vuoi essere davvero stravagante, puoi sostituire lo spazio con a^A, ma ciò rovescerebbe troppi avvisi (gli avvisi sono ignorabili). Non cambierà il conto in alcun modo, ma sicuramente sembra diverso.
Ismael Miguel,

4

Haskell (30 28 25 byte)

scanl1(\x y->y*div x y+y)

Versione estesa

f :: Integral n => [n] -> [n]
f xs = scanl1 increaseOnDemand xs
 where
   increaseOnDemand :: Integral n => n -> n -> n
   increaseOnDemand acc next = next * (1 + acc `div` next)

Spiegazione

scanl1consente di piegare un elenco e accumulare tutti i valori intermedi in un altro elenco. È una specializzazione di scanl, che ha il seguente tipo:

scanl  :: (acc  -> elem -> acc)  -> acc -> [elem] -> [acc]
scanl1 :: (elem -> elem -> elem) ->        [elem] -> [elem]

scanl1 f (x:xs) = scanl f x xs

Pertanto, tutto ciò di cui abbiamo bisogno è una funzione adatta che prende due l'ultimo elemento del nostro elenco ( accnella versione espansa) e quello che vogliamo elaborare ( nextnella versione espansa) e restituire un numero adatto.

Possiamo facilmente ricavare questo numero dividendo l'accumulatore per il successivo e pavimentando il risultato. divse ne occupa. Successivamente, dobbiamo semplicemente aggiungere 1per garantire che l'elenco stia effettivamente aumentando (e che non finiamo con 0).


Non è necessario assegnare un nome alla tua funzione. Puoi anche sostituire il ( ... )con $ ...e penso che tu abbia contato una nuova riga finale che può essere omessa: scanl1$\x y->y*div x y+y24 byte.
nimi,

@nimi: Davvero? Le espressioni contano? Detto questo, non salvo alcun byte con (...)vs $, poiché $\ viene analizzato come operatore e dopo avrei bisogno di un singolo spazio $.
Zeta,

le funzioni senza nome sono consentite per impostazione predefinita e scanl1(...)è una funzione senza nome. Per quanto riguarda $vs ().: hai ragione, errore mio.
nimi,

4

C ++, 63 60 57 byte

void s(int*f,int*e){for(int c=*f;++f!=e;c=*f+=c/ *f**f);}

Funziona sul posto data una gamma [first, last). Originariamente scritto come variante di modello, ma era più lungo:

template<class T>void s(T f,T e){for(auto c=*f;++f!=e;c=*f+=c/ *f**f);}

Versione estesa

template <class ForwardIterator>
void sort(ForwardIterator first, ForwardIterator last){
    auto previous = *first;

    for(++first; first != last; ++first){
        auto & current = *first;
        current += current * (current / previous);
        previous = current;
    }
}

3

CJam, 13 byte

q~{\_p1$/)*}*

Input come un elenco in stile CJam. L'uscita è separata dall'alimentazione di linea.

Provalo qui.

Spiegazione

q~    e# Read and evaluate input.
{     e# Fold this block over the list (i.e. "foreach except first")...
  \   e#   Swap with previous value.
  _p  e#   Duplicate and print previous value.
  1$  e#   Copy current value.
  /   e#   Integer division.
  )*  e#   Increment and multiply current value by the result.
}*

Il valore finale viene lasciato in pila e stampato automaticamente alla fine.


3

Matematica, 36 32 byte

 #2(Floor[#1/#2]+1)&~FoldList~#&

Test

#2(Floor[#1/#2]+1)&~FoldList~#& /@ {{5, 4, 12, 1, 3}, 
   {15, 8, 12, 47, 22, 15, 4, 66, 72, 15, 3, 4}}
(* {{5, 8, 12, 13, 15}, {15, 16, 24, 47, 66, 75, 76, 132, 144, 
  150, 153, 156}} *)

3

Perl, 17 + 3 = 20 byte

$p=$_*=$==1+$p/$_

Richiede -pe -lbandiere:

$ perl -ple'$p=$_*=$==1+$p/$_' <<< $'15\n8\n12\n47\n22\n15\n4\n66\n72\n15\n3\n4'
15
16
24
47
66
75
76
132
144
150
153
156

Spiegazione:

# '-p' reads each line into $_ and auto print
# '-l' chomp off newline on input and also inserts a new line when printing
# When assigning a number to `$=` it will automatic be truncated to an integer
# * Added newlines for each assignment 
$p=
  $_*=
    $==
      1+$p/$_

3

Python (3.5), 63 62 byte

def f(a):
 r=[0]
 for i in a:r+=i*(r[-1]//i+1),
 return r[1:]

Test

>>> print('\n'.join([str(i)+' => '+str(f(i)) for i in [[9],[1,2],[2,1],[7,3],[1,1,1,1],[5,4,12,1,3],[3,3,3,8,16],[6,5,4,3,2,1],[9,4,6,6,5,78,12,88],[8,9,41,5,12,3,5,6],[15,8,12,47,22,15,4,66,72,15,3,4]]]))
[9] => [9]
[1, 2] => [1, 2]
[2, 1] => [2, 3]
[7, 3] => [7, 9]
[1, 1, 1, 1] => [1, 2, 3, 4]
[5, 4, 12, 1, 3] => [5, 8, 12, 13, 15]
[3, 3, 3, 8, 16] => [3, 6, 9, 16, 32]
[6, 5, 4, 3, 2, 1] => [6, 10, 12, 15, 16, 17]
[9, 4, 6, 6, 5, 78, 12, 88] => [9, 12, 18, 24, 25, 78, 84, 88]
[8, 9, 41, 5, 12, 3, 5, 6] => [8, 9, 41, 45, 48, 51, 55, 60]
[15, 8, 12, 47, 22, 15, 4, 66, 72, 15, 3, 4] => [15, 16, 24, 47, 66, 75, 76, 132, 144, 150, 153, 156]

Soluzione precedente

alcune soluzioni ricorsive ma più grandi

(68 bytes) f=lambda a,i=0:[i,*f(a[1:],a[0]*(i//a[0]+1))][i==0:]if a!=[]else[i]
(64 bytes) f=lambda a,i=0:a>[]and[i,*f(a[1:],a[0]*(i//a[0]+1))][i<1:]or[i]

Inoltre, invece r+=[…], puoi usarer+=…,
Cyoce il

@Cyoce apporto modifiche ma quando ho definito r=[0]il parametro predefinito rdiventa non locale
Erwan,

hai ragione, ho dimenticato come Python ha gestito i parametri di default. L'altro suggerimento dovrebbe funzionare però
Cyoce l'

@Sì, sì, funziona grazie per i suggerimenti
Erwan,

3

Brachylog , 12 byte

{≤.;?%0∧}ᵐ<₁

Stranamente, il tentativo di moltiplicare ogni variabile per un numero inizierà a provare a moltiplicare per 2 e non per 0 o 1. Questo sembra funzionare e batte entrambe le altre implementazioni di Brachylog

Spiegazione

{       }ᵐ          --  Map each number
 ≤.                 --      to a number greater or equal to the original
  .;?%0             --      and a multiple of the original
       ∧            --      no more constraints
          <₁        --  so that the list is strictly increasing

Provalo online!


2

Brachylog , 54 byte

:_{h_.|[L:T],LhH,(T_,IH;0:$Ie*H=:T>I),Lb:I:1&:[I]rc.}.

Spiegazione

:_{...}.                § Call sub-predicate 1 with [Input, []] as input. Unify its output
                        § with the output of the main predicate


§ Sub-predicate 1

h_.                     § If the first element of the input is an empty list, unify the
                        § output with the empty list
|                       § Else
[L:T],LhH,              § Input = [L,T], first element of L is H
    (T_,IH              §     If T is the empty list, I = H
    ;                   §     Else
    0:$Ie*H=:T>I),      §     Enumerate integers between 0 and +inf, stop and unify the
                        §     enumerated integer with I only if I*H > T
Lb:I:1&                 § Call sub-predicate 1 with input [L minus its first element, I]
:[I]rc.                 § Unify the output of the sub-predicate with
                        § [I|Output of the recursive call]

2

Pyth, 11

t.u*Yh/NYQ0

Test Suite

Fa una riduzione cumulativa, una riduzione che restituisce tutti i valori intermedi, a partire da 0. Poiché è garantito che l'input contenga solo numeri interi positivi, va bene. In ogni passaggio, prendiamo il vecchio valore, lo dividiamo per il nuovo valore e aggiungiamo 1, quindi moltiplichiamo per il nuovo valore.


2

C, 79 byte

p;main(x,v)char**v;{for(;*++v;printf("%d ",p=((x+p-1)/x+!(p%x))*x))x=atoi(*v);}

Ungolfed

p; /* previous value */

main(x,v) char**v;
{
    /* While arguments, print out x such that x[i] > x[i-1] */
    for(;*++v; printf("%d ", p = ((x+p-1)/x + !(p%x)) * x))
        x = atoi(*v);
}

Non p=p/x*x+xfunzionerebbe?
Neil,

@Neil Sì, funzionerebbe. Decisamente ripensato a questo :)
Cole Cameron,

2

PowerShell, 26 byte

$args[0]|%{($l+=$_-$l%$_)}

Accetta input come array esplicito, ad es . > .\sort-by-multiplying.ps1 @(6,5,4,3,2,1)Tramite $args[0].

Quindi |%{...}eseguiamo il loop-over su quello con e ogni iterazione esegue la magia . No, sto scherzando, si usa lo stesso trucco modulo di altre risposte (puntelli per @aross perché ho notato che prima).

Le parentesi incapsulanti (...)assicurano che il risultato dell'operazione matematica sia posizionato sulla tubazione e quindi emesso. Se li interrompessimo, non verrebbe emesso nulla poiché la $lvariabile viene raccolta in modo inutile al termine dell'esecuzione.

Esempio

PS C:\Tools\Scripts\golfing> .\sort-by-multiplying.ps1 @(8,9,1,5,4)
8
9
10
15
16

1

Japt, 11 byte

Uå@Y*-~(X/Y

Provalo online!

Come funziona

          // Implicit: U = input array of integers
Uå@       // Cumulative reduce: map each previous value X and current value Y to:
-~(X/Y    //  floor(X/Y+1).
          // Implicit: output last expression

1

05AB1E , 11 byte

Codice:

R`[=sŽDŠ/ò*

Provalo online!

Spiegazione:

R            # Reverse input
 `           # Flatten the list
  [          # While loop
   =         # Print the last item
    s        # Swap the last two items
     Ž       # If the stack is empty, break
      D      # Duplicate top of the stack
       Š     # Pop a,b,c and push c,a,b
        /    # Divide a / b
         ò   # Inclusive round up
          *  # Multiply the last two items

Utilizza la codifica CP-1252.


1

Minkolang 0,15 , 17 byte

nd1+?.z0c:1+*d$zN

Provalo qui!

Spiegazione

nd                   Take number from input and duplicate it
  1+                 Add 1
    ?.               Stop if top of stack is 0 (i.e., when n => -1 because input is empty).
      z              Push value from register
       0c            Copy first item on stack
         :           Pop b,a and push a//b
          1+         Add 1
            *        Multiply
             d$z     Duplicate and store in register
                N    Output as number

In sostanza, il registro mantiene l'ultimo membro dell'elenco crescente e questo viene diviso per l'input e incrementato per ottenere il moltiplicatore per il membro successivo. La caratteristica toroidale del campo di codice di Minkolang significa che scorre in senso orizzontale senza necessità ()o []cicli.


1

Brachylog , 21 byte

l~lCℕ₁ᵐ≤ᵛ~+?&;Cz≜×ᵐ<₁

Provalo online!

Utilizza la somma dei valori di input come limite superiore per i coefficienti C. Abbastanza lento, timeout su TIO per lunghezze dell'elenco di input oltre 5 o 6 (anche in base alla somma dei valori). Ma non è lento come la mia versione originale, che richiede piccoli elenchi di fino a 3 elementi, con valori minuscoli, per non scadere:

21 byte

l~l.&+^₂⟦₁⊇.;?z/ᵐℕ₁ᵐ∧

Provalo online!



1

Python 2 , 53 byte

lambda a:reduce(lambda b,v:b+[b[-1]/v*v+v],a,[0])[1:]

Provalo online!

k*x>yimplica k>y/x; quindi il più piccolo kpuò essere k=floor(y/x)+1. Poiché in Python 2.7, la divisione intera è già considerata come floor, vogliamo k=y/x+1e k*x = (y/x+1)*x = y/x*x+x.


0

Oracle SQL 11.2, 210 byte

WITH v AS(SELECT TO_NUMBER(COLUMN_VALUE)a,rownum i FROM XMLTABLE(('"'||REPLACE(:1,' ','","')||'"'))),c(p,n)AS(SELECT a,2 FROM v WHERE i=1UNION ALL SELECT a*CEIL((p+.1)/a),n+1 FROM c,v WHERE i=n)SELECT p FROM c;

Un-golfed

WITH v AS                                           
(
  SELECT TO_NUMBER(COLUMN_VALUE)a, rownum i            -- Convert the input string into rows 
  FROM   XMLTABLE(('"'||REPLACE(:1,' ','","')||'"'))   -- using space as the separator between elements
)
, c(p,n) AS                        
(
  SELECT a, 2 FROM v WHERE i=1                         -- Initialize the recursive view
  UNION ALL 
  SELECT a*CEIL((p+.1)/a),n+1 FROM c,v WHERE i=n       -- Compute the value for the nth element
)
SELECT p FROM c;

0

Chez Scheme (140 byte)

Versione golfizzata:

(define(f l)(define(g l p m)(cond((null? l)l)((<(*(car l)m)(+ p 1))(g l p(+ m 1)))(else(cons(*(car l)m)(g(cdr l)(* m(car l))1)))))(g l 0 1))

Versione Ungolfed:

(define(f l)
  (define(g l p m)
    (cond
      ((null? l) l)
      ((< (* (car l) m) (+ p 1)) (g l p (+ m 1)))
      (else (cons (* (car l) m) (g (cdr l) (* m (car l)) 1)))
    )
  )
  (g l 0 1)
)

Provalo online!


* m(car l)può essere *(car l)m.
Jonathan Frech,

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.