Pinta esa cerca

9

Eres Tom Sawyer y tienes que pintar una cerca de 102400 m de largo. Afortunadamente, tus amigos decidieron ayudarte a cambio de varias cosas. Cada amigo pintará L metros, a partir de S con el color C . S , L son una cantidad entera de metros y 1 ≤ C ≤ 97. Aburriéndote, decides averiguar cuántos metros de cada color tienes.

Entrada

La entrada se lee desde la entrada estándar. Cada línea contiene tres números S , L , C como se describió anteriormente.

Ouput

La salida se escribe en la salida estándar. Para cada color que aparece en el cercado final, imprima el número de color y la cantidad de veces que aparece. Ordenar por colores.

Ejemplos

Entrada 0

                           ..............
0 3 1                      111...........
2 4 2                      112222........
1 2 3                      133222........
0 4 1                      111122........
7 3 5                      111122.555....

Salida 0

1 4
2 2
5 3

Entrada 1

 0 100 1
 50 150 2

Salida 1

 1 50
 2 150

Entrada 2

 500 1000 1
 0 2000 2

Salida 2

 2 2000

Más ejemplos

Aquí hay un pequeño generador:

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>


/* From http://en.wikipedia.org/wiki/Random_number_generation */
unsigned m_w;
unsigned m_z;

unsigned get_random()
{
  m_z = 36969 * (m_z & 65535) + (m_z >> 16);
  m_w = 18000 * (m_w & 65535) + (m_w >> 16);
  return (m_z << 16) + m_w;  /* 32-bit result */
}

int main(int argc, char **argv)
{
  int i;

  assert(argc == 2);
  m_w = 0xbabecafe;
  m_z = atoi(argv[1]);

  i = 10;
  while (i--);
    get_random();

  i = atoi(argv[1]);
  while (i--) {
    int s = (int) ((get_random() << 8) % 102397);
    int l = (int) ((get_random() << 8) % (102397 - s));
    int c = (int) ((get_random() << 8) % 97 + 1);
    printf("%d %d %d\n", s, l, c);
  }

  return 0;
}

Ejecutando ejemplos:

$ ./gen 1 | ./paint
6 535
$ ./gen 10 | ./paint
28 82343
36 3476
41 1802
49 4102
82 1656
$ ./gen 100 | ./paint
2 2379
22 17357
24 4097
25 1051
34 55429
42 9028
45 9716
66 1495
71 196
85 640
97 706
$ ./gen 1000 | ./paint
16 719
26 29
28 24
33 1616
55 371
65 35
69 644
74 16
84 10891
86 36896
87 50832
89 19
$ ./gen 10000 | ./paint
3 800
6 5712
14 3022
17 16
26 1
29 18770
31 65372
37 387
44 40
49 37
50 93
55 11
68 278
70 19
71 64
72 170
77 119
78 6509
89 960
97 15
$ ./gen 100000 | ./paint
2 6
8 26
12 272
24 38576
26 1
34 1553
35 8
36 19505
43 2
45 11
46 2
47 9
49 27339
50 139
53 3109
69 11744
92 89
$ ./gen 1000000 | ./paint
1 1
3 4854
6 523
13 1
16 11
18 416
22 7
24 3920
25 96
31 10249
32 241
37 1135
45 10
57 758
62 2348
65 11
66 7422
78 6
85 13361
87 3833
88 187
91 46
93 7524
96 45436

Su programa debe ejecutarse en un tiempo razonable. Mi solución se ejecuta en unos segundos en el último ejemplo.

El código más corto gana.

Incluya el tiempo de ejecución y su salida para la última prueba.

EDITAR : Este problema no pretende ser forzado por la fuerza bruta, por lo que una solución trivial no es aceptable.

Alexandru
fuente
Me parece que la forma más simple (asignar matriz, llenarla, contar # de cada color en la matriz, salida) se ejecutaría en un tiempo razonable. Sin embargo, parece que tenía la intención de crear un algoritmo como parte del desafío: ¿me equivoco?
Matthew leyó el
Estaba pensando que 1000000 operaciones X 25000 longitud promedio = 25 * 10 ^ 9 no se ejecutarían en un tiempo razonable. Puedo aumentar la longitud de la cerca si piensas lo contrario.
Alexandru
Ah, me perdí que la entrada fue un millón de líneas, mi mal.
Matthew leyó el
1
@Keith: Unidades Imperiales ITYM : en.wikipedia.org/wiki/Imperial_units
Paul R
1
Keith: Creo que puedes asumir que un Tom Sawyer hoy sería mucho más sensato y usaría SI.
Joey

Respuestas:

2

Python, 221 239 caracteres

import sys
F=[]
for L in sys.stdin:s,l,c=map(int,L.split());F=sum([[(a,min(b,s),d)]*(a<s)+[(max(a,s+l),b,d)]*(b>s+l)for a,b,d in F],[(s,s+l,c)])
C=[0]*98
for a,b,c in F:C[c]+=b-a
for c in range(98):
 if C[c]:print c,C[c]

Se mantiene Fcomo una lista desordenada de triples (inicio de ejecución, final de ejecución, color) que representan el estado actual de la cerca. Dado que la pintura aleatoria en el generador sobrepasa grandes cantidades de franjas con bastante frecuencia, esta lista nunca es demasiado larga (generalmente en el rango de 15-40).

Se ejecuta en 37 segundos en el ejemplo 1M.

Keith Randall
fuente
puede usar G+=[(a,min(b,s),d)]*(a<s)etc. para obtener el bucle for en una línea
gnibbler
for C in sorted(f[2] for f in F):print C,sum(b-a for a,b,c in F if c==C)guarda un par de caracteres en las últimas cuatro líneas y evita la necesidad de conocer el número mágico 98.
@Gareth: creo que imprimiría duplicados si el mismo color fuera utilizado por más de un rango. Tendría que haber unificación en algún lugar ...
Keith Randall
Tienes razón: tendría que ser lo sorted(set(...))que ya no es una mejora.
1

Haskell, 251 261 269 294 caracteres

import Data.List
w@(y@(f,d,e):z)§x@[a,b,c]|e<=d=z§x|a+b>d=(f,d,e`min`a):((f,a+b,e):z)§x
w§[a,b,c]=(c,a,a+b):w
r(c,a,b)=replicate(b-a)c
f l=shows(l!!0)" "++shows(length l)"\n"
main=interact$(>>=f).group.(>>=r).sort.foldl'(§)[].map(map read.words).lines

Algo no está del todo bien ya que lleva demasiado tiempo y se acumula ... Pero produce las respuestas correctas:

$> ghc -O3 --make -rtsopts -with-rtsopts -K32m 3095-PaintTheFence.hs 
Linking 3095-PaintTheFence ...

$> ./3095-gen 1000000 | time ./3095-PaintTheFence
1 1
3 4854
6 523
13 1
16 11
18 416
22 7
24 3920
25 96
31 10249
32 241
37 1135
45 10
57 758
62 2348
65 11
66 7422
78 6
85 13361
87 3833
88 187
91 46
93 7524
96 45436
       43.99 real        43.42 user         0.46 sys

  • Editar (294 → 269) replicatey groupes una forma tan eficiente de contar la pintura, y requiere menos código que la función personalizadas
  • Editar (269 → 261) no es necesario maxllamar
  • Editar (261 → 251) no es necesario eliminar la pintura 0 en f
MtnViewMark
fuente
Es demasiado lento .
Alexandru
Es código golf, ¿no? Para el código de golf, usualmente restricciones como "tiempo razonable" significan que para el tamaño de entrada objetivo, no puede tomar días. ¿Hay algún criterio por el cual 37 segundos (el tiempo de la otra respuesta) está bien, pero 44 segundos es demasiado lento? ¡Podría cronometrar el mío en una CPU más rápida si lo desea!
MtnViewMark
En este caso, debería demorar unos segundos * la desaceleración del idioma. Corrígeme si me equivoco, pero ¿Haskell no es mucho más rápido que Python? (razón por la cual no rechacé la solución de Keith). Hubo una solución de fuerza bruta C publicada que tomó alrededor del mismo tiempo que, según las reglas, no estaba permitido.
Alexandru
Medido en la misma máquina, que no funcione mucho más rápido que la solución de Python. La solución de Python tarda 133.556 segundos en mi máquina. La solución de Haskell es 3 veces más rápida. (. Por lo que supongo que significar simplemente la construcción de una gran variedad de colores de la longitud de la pared) También, nota que esta solución Haskell no es una solución "fuerza bruta"
MtnViewMark
0

Perl - 148 bytes

Parece que Perl es el mejor para jugar. Fácil de codificar más corto y más rápido. ;)

código:

#!perl -n
($a,$b,$c)=split;substr($s,$a,$b,chr($c)x$b)}BEGIN{$s="z"x102400}{$s=~s/([^z])\1*/$H{$1}+=length$&/ge;print ord," $H{$_}
"for sort keys%H

hora:

time ./gen 1000000 | perl paint.pl
...
real    0m9.767s
user    0m10.117s
sys 0m0.036s
Hojung Youn
fuente
0
$ cat input.txt
0 3 1
2 4 2
1 2 3
0 4 1
7 3 5

$ cat input.txt  | perl -anE '@a[$F[0]..$F[0]+$F[1]]=($F[2])x$F[1];END{$i[$_]++for@a;$i[$_]&&say"$_ $i[$_]"for 1..$#i}'
1 4
2 1
5 3


$ cat input2.txt
500 1000 1
0 2000 2

$ cat input2.txt  | perl -anE '@a[$F[0]..$F[0]+$F[1]]=($F[2])x$F[1];END{$i[$_]++for@a;$i[$_]&&say"$_ $i[$_]"for 1..$#i}'
2 2000
aero
fuente
0

JavaScript, 183 caracteres, 1.3 segundos

Lamentablemente, tuve que cortar la parte stdin / out del requisito, que JavaScript no admite. En cambio, recibo la entrada de una carga de archivo <input>(que no cuento en mi cuenta de caracteres, aunque probablemente debería).

Aquí está la versión sin golf. Es una función que toma la cadena de entrada completa ... ¡todos los 14 MB! Este es el que toma 1.3 segundos; la versión de golf dura aproximadamente el doble, ¡pero aún supera a las otras soluciones! Curiosamente, es dos veces más rápido en Firefox que en Chrome. Demostración en vivo aquí .

function Q(input) {

    var c = [];
    var l = input.trim().split(/\s/g);
    input = null
    var length = l.length;

    // Loop through each meter of the wall...
    for (var i = 0; i <= 102400; i++) {

        // ...and loop through each of the friends, finding
        // the last one who painted this meter...
        for (var j = length; j > 0; ) {
            j -= 3;

            // Start = +l[j]
            // Length = +l[j + 1]
            // Color = +l[j + 2]

            var S = +l[j];      
            if (S <= i && +l[j + 1] + S > i) {

                // ...and incrementing the color array.
                var C = +l[j + 2];
                if (!++c[C])
                    c[C] = 1;

                break;
            }
        }
    }

    console.log(c.map(function (a,b) {return b + ' ' + a}).filter(function (a) { return a }).join('\n'));
}

Y aquí está la versión de golf.

function G(i){l=i.trim(c=[]).split(/\s/)
for(i=0;i<102401;i++)for(j=l.length;j>0;)if(l[j-=3]<=i&&i-l[j+1]<l[j]){if(!++c[l[j+2]])c[l[j+2]]=1
break}for(k in c)console.log(k+' '+c[k])}

captura de pantalla

Casey Chu
fuente