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.


¿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.


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>


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

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.

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


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;
    }
}

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.


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

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/$_

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]

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!


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]

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.


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);
}

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

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

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.


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.


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!



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.


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;

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!


* m(car l)puede ser *(car l)m.
Jonathan Frech

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.