Ordenar por multiplicación

34

Debería escribir un programa o función que, dada una lista de enteros positivos, multiplique cada elemento con el entero positivo más pequeño posible para crear una lista estrictamente creciente.

Por ejemplo si la entrada es

5 4 12 1 3

las multiplicaciones serán

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

y la salida será la lista creciente

5 8 12 13 15

Entrada

  • Una lista de enteros positivos que contiene al menos 1 elemento

Salida

  • Una lista de enteros positivos

Ejemplos

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

Este es el código de golf, por lo que gana el programa o función más corto.

Dato curioso: el último elemento de la salida para la entrada N, N-1, ... ,1parece ser el (N+1)thelemento de la secuencia A007952 . Si encuentra una prueba, puede incluirla en su respuesta de golf o publicarla como comentario.

randomra
fuente
¿Alguien ha hecho algo con esa prueba todavía?
Connor Clark

Respuestas:

20

Jalea , 6 5 bytes

:‘×µ\

Primera respuesta de Jelly antes de que @Dennis se despierte y me golpee. Pruébalo en línea!

Explicación

:          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

Gracias a @Dennis por -1 byte.

Sp3000
fuente
44
:‘×µ\Guarda un byte.
Dennis
20
@Dennis Oh, mierda, se despertó
Dennis van Gils
9

JavaScript (ES6), 28

Editar Según lo sugerido por @Patrick Roberts, ppuede ser un parámetro no inicializado. Mismo recuento de bytes pero evite usar una variable global

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

PRUEBA

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>

edc65
fuente
Creo que puede guardar algunos bytes usando el módulo, tal como lo hice en mi respuesta .
Aross
¿No puedes saltarte el p = 0? Lo necesita para ejecutarlo en varias listas, pero la pregunta es solo para una sola lista
Charlie Wynn
1
@CharlieWynn si no inicializa una variable, obtiene el error para la variable indefinida. Si por casualidad la variable ya existe (eso podría suceder fácilmente en el entorno de una página web), podría tener un valor incorrecto.
edc65
@ edc65 efectivamente, p ya está definido en esta página!
Charlie Wynn
1
@PatrickRoberts a pensar de nuevo, todavía podía evitar globales: f=a=>a.map(n=>a+=n-a%n,a=0). Pero no es mi algoritmo (tonto), así que me quedaré con el mío tal como está y votaré aross
edc65
6

Python 2, 67 64 bytes

Primero intente jugar golf con código, por lo que se agradecen los consejos.

def m(l):
 for x in range(1,len(l)):l[x]*=l[x-1]/l[x]+1
 print l
Taronyu
fuente
Hola, creo que estás contando los retornos de línea como 2 bytes cada uno (¿usando Windows?), Pero en este sitio cuentas cada retorno de línea como un solo byte. Entonces su puntaje es en realidad 65 bytes. (Puede copiar y pegar su código en mothereff.in/byte-counter si no está seguro). Además, puede hacerlo en print llugar de return lguardar otro byte. ¡Buen trabajo!
Mathmandan
Gracias, no sabía sobre los retornos de línea. Eso explica por qué siempre tengo diferentes conteos de bytes. Y ni siquiera consideré que la impresión es suficiente y no tiene que devolver la lista.
Taronyu
¡No hay problema! Por cierto, ya que mencionó que "los consejos son apreciados", podría estar interesado en navegar a través de codegolf.stackexchange.com/questions/54/… . ¡Disfrutar!
Mathmandan
5

PHP, 55 46 42 41 bytes

Utiliza la codificación ISO 8859-1.

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

Ejecutar así ( -dagregado solo por estética):

php -d error_reporting=30709 -r 'for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,~ß;' 10 10 8
  • Guardado 1 byte gracias a Ismael Miguel.
  • Se guardaron 8 bytes mediante el uso de módulo en lugar de piso
  • Guardado 4 bytes thx a Ismael Miguel (para en lugar de foreach)
  • Se guardó un byte al usar para producir un espacio.
aross
fuente
Creo que puedes reemplazarlo $a+0con +$a. Además, puede suponer que la entrada nunca tendrá un 0, por lo tanto, puede reemplazar su $a+0&&printcon simplemente +$a&print. De hecho, incluso podrías hacerlo $a&print, ya que en PHP "0" == 0 == 0.0 == false. Pero puede que no sea necesario si solo usa un echo, creo.
Ismael Miguel
El binario andno funcionará (a diferencia de lo lógico), ni el eco funcionará de esta manera. Como estoy tomando datos de CLI, el primer argumento es -, que quiero atrapar en lugar de imprimir un cero. Tratar php -r 'print_r($argv);' foo. Sin embargo, guardé 1 byte con su primera sugerencia, gracias.
aross
1
¿Qué tal for(;$a=$argv[++$i];)echo$l+=$a-$l%$a,' ';? Tiene 42 bytes de longitud y omite el primer elemento.
Ismael Miguel
Nice one, thx @IsmaelMiguel
aross
De nada. Si quieres ser realmente pervertido, puedes reemplazar el espacio con a^A, pero eso derramaría demasiadas advertencias (las advertencias son ignorables). No cambiará el bytecount de ninguna manera, pero definitivamente se ve diferente.
Ismael Miguel
4

Haskell (30 28 25 bytes)

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

Versión ampliada

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)

Explicación

scanl1le permite plegar una lista y acumular todos los valores intermedios en otra lista. Es una especialización de scanl, que tiene el siguiente tipo:

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

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

Por lo tanto, todo lo que necesitamos es una función adecuada que tome dos, el último elemento de nuestra lista ( accen la versión expandida) y el que deseamos procesar ( nexten la versión expandida) y devolver un número adecuado.

Podemos derivar fácilmente este número dividiendo el acumulador entre el siguiente y colocando el resultado en el suelo. divse encarga de eso. Luego, simplemente tenemos que agregar 1para asegurarnos de que la lista realmente esté aumentando (y que no terminemos con 0).

Zeta
fuente
No es necesario darle un nombre a su función. También puede reemplazar ( ... )con $ ...y creo que ha contado una nueva línea final que se puede omitir: scanl1$\x y->y*div x y+y24 bytes.
nimi
@nimi: ¿En serio? Las expresiones cuentan? Dicho esto, no guardo ningún byte con (...)vs $, ya que $\ se analiza como operador y necesitaría un solo espacio después $.
Zeta
las funciones sin nombre están permitidas por defecto y scanl1(...)es una función sin nombre. Con respecto a $vs ().: tienes razón, mi error.
nimi
4

C ++, 63 60 60 57 bytes

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

Funciona en el lugar dado un rango [first, last). Originalmente escrito como variante de plantilla, pero eso fue más largo:

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

Versión extendida

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;
    }
}
Zeta
fuente
3

CJam, 13 bytes

q~{\_p1$/)*}*

Ingrese como una lista de estilo CJam. La salida está separada de salto de línea.

Pruébalo aquí.

Explicación

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.
}*

El valor final se deja en la pila y se imprime automáticamente al final.

Martin Ender
fuente
3

Mathematica 36 32 bytes

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

Prueba

#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}} *)
Jason B.
fuente
3

Perl, 17 + 3 = 20 bytes

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

Requiere -py -lbanderas:

$ 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

Explicación:

# '-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/$_
andlrc
fuente
3

Python (3.5), 63 62 bytes

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

Prueba

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

Solución previa

algunas soluciones recursivas pero más grandes

(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]
Erwan
fuente
También en lugar de r+=[…], puedes usarr+=…,
Cyoce
@Cyoce realizo cambios, pero cuando definí el r=[0]parámetro predeterminado se rconvirtió en no local
Erwan
tienes razón, olvidé cómo Python manejó los parámetros predeterminados. Sin embargo
Cyoce,
@Cyoce sí, funciona gracias por consejos
Erwan
3

Brachylog , 12 bytes

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

Lo suficientemente extraño como tratar de multiplicar cada variable por un número comenzará a tratar de multiplicar por 2 y no por 0 o 1. Sin embargo, esto parece funcionar y supera las otras dos implementaciones de Brachylog

Explicación

{       }ᵐ          --  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

Pruébalo en línea!

Kroppeb
fuente
2

Brachylog , 54 bytes

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

Explicación

:_{...}.                § 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]
Fatalizar
fuente
2

Pyth, 11

t.u*Yh/NYQ0

Banco de pruebas

Hace una reducción acumulativa, una reducción que devuelve todos los valores intermedios, comenzando por 0. Como se garantiza que la entrada solo contiene enteros positivos, está bien. En cada paso, tomamos el valor anterior, lo dividimos por el nuevo valor y lo sumamos 1, luego lo multiplicamos por el nuevo valor.

FryAmTheEggman
fuente
2

C, 79 bytes

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

Sin golf

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);
}
Cole Cameron
fuente
No p=p/x*x+xfuncionaria?
Neil
@Neil Sí, eso funcionaría. Definitivamente pensé demasiado en esto :)
Cole Cameron
2

PowerShell, 26 bytes

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

Toma la entrada como una matriz explícita, por ejemplo, > .\sort-by-multiplying.ps1 @(6,5,4,3,2,1) vía $args[0].

Entonces for-loop sobre eso con |%{...}y cada iteración realiza magia . No, es broma, usamos el mismo truco de módulo que otras respuestas (accesorios para @aross porque lo vi allí primero).

Los padres encapsulantes (...) aseguran que el resultado de la operación matemática se coloque en la tubería y, por lo tanto, se genere. Si los dejáramos, no se generaría nada ya que la $lvariable se recolecta basura después de que finaliza la ejecución.

Ejemplo

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

Japt, 11 bytes

Uå@Y*-~(X/Y

¡Pruébelo en línea!

Cómo funciona

          // 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
ETHproducciones
fuente
1

05AB1E , 11 bytes

Código:

R`[=sŽDŠ/ò*

Pruébalo en línea!

Explicación:

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

Utiliza la codificación CP-1252.

Adnan
fuente
1

Minkolang 0.15 , 17 bytes

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

Pruébalo aquí!

Explicación

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

Esencialmente, el registro mantiene el último miembro de la lista ascendente y esto se divide por la entrada y se incrementa para obtener el multiplicador para el siguiente miembro. La función de los medios de campo toroidal código de Minkolang que se realiza un bucle horizontalmente sin la necesidad de ()o []bucles.

El'endia Starman
fuente
1

Brachylog , 21 bytes

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

Pruébalo en línea!

Utiliza la suma de valores de entrada como límite superior para los coeficientes C. Bastante lento, agota el tiempo de espera en TIO para longitudes de lista de entrada más allá de 5 o 6 (también dependiendo de la suma de los valores). Pero no es tan lento como mi versión original, que requiere pequeñas listas de hasta 3 elementos, con pequeños valores, para no agotar el tiempo de espera:

21 bytes

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

Pruébalo en línea!

sundar - Restablece a Monica
fuente
1

Python 2 , 53 bytes

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

Pruébalo en línea!

k*x>yimplica k>y/x; entonces el más pequeño kpuede ser es k=floor(y/x)+1. Como en Python 2.7, la división de enteros ya se toma como floor, queremos k=y/x+1, y k*x = (y/x+1)*x = y/x*x+x.

Chas Brown
fuente
0

Oracle SQL 11.2, 210 bytes

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;

Sin golf

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;
Jeto
fuente
0

Esquema Chez (140 bytes)

Versión de golf:

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

Versión sin golf:

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

Pruébalo en línea!

Algodón Zachary
fuente
* m(car l)puede ser *(car l)m.
Jonathan Frech