Dipingi quel recinto


9

Sei Tom Sawyer e devi dipingere un recinto di 102400 m di lunghezza. Fortunatamente, i tuoi amici hanno deciso di aiutarti in cambio di varie cose. Ogni amico dipingerà L metri, partendo da S con il colore C . S , L sono numeri interi di metri e 1 ≤ C ≤ 97. Annoiarsi, decidi di scoprire quanti metri di ogni colore hai.

Ingresso

L'input viene letto dall'input standard. Ogni riga contiene tre numeri S , L , C come descritto sopra.

ouput

L'output viene scritto nell'output standard. Per ogni colore che appare sul recinto finale, stampare il numero del colore e il numero di volte che appare. Ordina per colori.

Esempi

Ingresso 0

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

Uscita 0

1 4
2 2
5 3

Ingresso 1

 0 100 1
 50 150 2

Uscita 1

 1 50
 2 150

Ingresso 2

 500 1000 1
 0 2000 2

Uscita 2

 2 2000

Più esempi

Ecco un piccolo generatore:

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

Esempi in corso:

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

Il programma deve essere eseguito in tempi ragionevoli. La mia soluzione viene eseguita in pochi secondi sull'ultimo esempio.

Il codice più corto vince.

Includi il tempo di esecuzione e l'output per l'ultimo test.

EDIT : questo problema non è destinato a essere forzato, quindi una soluzione banale non è accettabile.


Mi sembra che il modo più semplice (alloca array, riempilo, conta # di ogni colore in array, output) funzionerebbe in un tempo ragionevole. Sembra che tu abbia voluto inventare un algoritmo per far parte della sfida, però: sbaglio?
Matteo Leggi il

Stavo pensando che 1000000 ops X 25000 lunghezza media = 25 * 10 ^ 9 non funzionerebbero in tempi ragionevoli. Posso aumentare la lunghezza della recinzione se la pensi diversamente.
Alexandru,

Ah, mi mancava che l'input fosse un milione di righe, mia cattiva.
Matteo Leggi il

1
@Keith: ITYM Imperial Units : en.wikipedia.org/wiki/Imperial_units
Paul R

1
Keith: Penso che tu possa presumere che un Tom Sawyer oggi sarebbe molto più sensato e userebbe SI.
Joey,

Risposte:


2

Python, 221 239 caratteri

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]

Mantiene Fun elenco non ordinato di triple (inizio della corsa, fine della corsa, colore) che rappresentano lo stato corrente della recinzione. Poiché la pittura casuale nel generatore supera di gran lunga larghezze abbastanza frequentemente, questo elenco non è mai troppo lungo (in genere nell'intervallo 15-40).

Viene eseguito in 37 secondi sull'esempio 1M.


puoi usare G+=[(a,min(b,s),d)]*(a<s)ecc. per ottenere il ciclo for su una riga
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)salva un paio di caratteri sulle ultime quattro righe ed evita la necessità di conoscere il numero magico 98.

@Gareth: penso che stamperebbero i duplicati se lo stesso colore fosse usato da più di una gamma. Dovrebbe esserci unificazione in qualche luogo ...
Keith Randall,

Hai ragione: dovrebbe essere quello sorted(set(...))che non è più un miglioramento.

1

Haskell, 251 261 269 294 caratteri

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

Qualcosa non è del tutto corretto in quanto richiede troppo tempo e si impila ... Ma produce le risposte giuste:

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

  • Modifica (294 → 269) replicateed groupè un modo altrettanto efficace di contare il colore e richiede meno codice della funzione personalizzatas
  • Modifica (269 → 261) non è necessario maxchiamare
  • Modifica (261 → 251) non è necessario eliminare la vernice da 0 pollici f

È troppo lento .
Alexandru,

È code-golf, no? Per il code-golf, in genere restrizioni come "tempo ragionevole" significano che per le dimensioni di input target non possono essere necessari giorni. Esistono dei criteri per cui 37 secondi (il tempo dell'altra risposta) va bene, ma 44 secondi sono troppo lenti? Potrei solo passare il tempo su una CPU più veloce se vuoi!
MtnViewMark,

In questo caso, il rallentamento della lingua dovrebbe richiedere alcuni secondi *. Correggimi se sbaglio, ma Haskell non è molto più veloce di Python? (motivo per cui non ho votato in negativo la soluzione di Keith). Esisteva una soluzione di forza bruta C impiegata nello stesso periodo che, secondo le regole, non era consentita.
Alexandru,

Misurato sulla stessa macchina, si fa molto più veloce rispetto alla soluzione Python. La soluzione Python impiega 133.556 secondi sulla mia macchina. La soluzione Haskell è 3 volte più veloce. Inoltre, nota che questa soluzione di Haskell non è una soluzione di "forza bruta" (per cui immagino che intendi semplicemente costruire una serie di colori la lunghezza del muro.)
MtnViewMark

0

Perl - 148 byte

Sembra che Perl sia il migliore con cui giocare. facile da programmare più breve e più veloce. ;)

codice:

#!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

tempo:

time ./gen 1000000 | perl paint.pl
...
real    0m9.767s
user    0m10.117s
sys 0m0.036s

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

0

JavaScript, 183 caratteri, 1,3 secondi

Purtroppo, ho dovuto tagliare la parte stdin / out del requisito, che JavaScript non supporta. Invece, ottengo invece l'input da un caricamento di file <input>(che non conto nel mio conteggio dei caratteri, anche se probabilmente dovrei).

Ecco la versione ungolfed. È una funzione che accetta l'intera stringa di input ... tutti i 14 MB di essa! Questo è quello che richiede 1,3 secondi; la versione golfizzata dura circa il doppio, ma batte comunque le altre soluzioni! È interessante notare che è due volte più veloce in Firefox che in Chrome. Demo live qui .

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

Ed ecco la versione 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])}

immagine dello schermo

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.