Pomaluj to ogrodzenie


9

Jesteś Tomem Sawyerem i musisz pomalować ogrodzenie o długości 102400 m. Na szczęście twoi przyjaciele postanowili ci pomóc w zamian za różne rzeczy. Każdy znajomy farby L m, wychodząc z S z kolorem C . S , L to całkowita liczba metrów i 1 ≤ C ≤ 97. Nudząc się, decydujesz się dowiedzieć, ile metrów masz każdego koloru.

Wejście

Wejście jest odczytywane ze standardowego wejścia. Każda linia zawiera trzy liczby S , L , C, jak opisano powyżej.

Ouput

Wyjście jest zapisywane na standardowe wyjście. Dla każdego koloru, który pojawia się na ostatnim ogrodzeniu, wydrukuj numer koloru i liczbę razy, kiedy się pojawi. Sortuj według kolorów.

Przykłady

Wprowadź 0

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

Wyjście 0

1 4
2 2
5 3

Wejście 1

 0 100 1
 50 150 2

Wyjście 1

 1 50
 2 150

Wejście 2

 500 1000 1
 0 2000 2

Wyjście 2

 2 2000

Więcej przykładów

Oto mały generator:

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

Uruchamianie przykładów:

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

Twój program musi zostać uruchomiony w rozsądnym czasie. Moje rozwiązanie działa w ciągu kilku sekund na ostatnim przykładzie.

Najkrótszy kod wygrywa.

Uwzględnij czas działania i wyniki dla ostatniego testu.

EDYCJA : Ten problem nie ma być brutalny, więc trywialne rozwiązanie jest niedopuszczalne.


Wydaje mi się, że najprostszy sposób (przydzielenie tablicy, wypełnienie jej, policzenie # każdego koloru w tablicy, wyjście) przebiegnie w rozsądnym czasie. Wygląda na to, że zamierzałeś wymyślić algorytm, który będzie częścią wyzwania - czy się mylę?
Mateusz

Myślałem, że 1000000 operacji X 25000 średnia długość = 25 * 10 ^ 9 nie będzie działać w rozsądnym czasie. Mogę zwiększyć długość ogrodzenia, jeśli uważasz inaczej.
Alexandru

Ach, tęskniłem za tym, że dane wejściowe to milion linii, moje złe.
Matthew

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

1
Keith: Myślę, że możesz założyć, że Tom Sawyer byłby dzisiaj bardziej rozsądny i użyłby SI.
Joey,

Odpowiedzi:


2

Python, 221 239 znaków

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]

Zachowuje się Fjako nieuporządkowana lista potrójnych (początek, koniec i kolor) reprezentujących bieżący stan ogrodzenia. Ponieważ losowe malowanie w generatorze zbyt często maluje pokosy dość często, lista ta nigdy nie jest zbyt długa (zazwyczaj w zakresie 15-40).

Działa za 37 sekund na przykładzie 1M.


możesz użyć G+=[(a,min(b,s),d)]*(a<s)itp., aby uzyskać pętlę for w jednym wierszu
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)zapisuje kilka znaków w ostatnich czterech liniach i unika potrzeby znajomości magicznej liczby 98.

@Gareth: Myślę, że wydrukowałoby duplikaty, gdyby ten sam kolor był używany przez więcej niż jeden zakres. Musi tam być gdzieś unifikacja ...
Keith Randall

Masz rację: musiałoby to być, sorted(set(...))co nie jest już poprawą.

1

Haskell, 251 261 269 294 znaków

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

Coś w tym jest nie tak, ponieważ zajmuje dużo czasu i nakłada się na siebie ... Ale daje właściwe odpowiedzi:

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

  • Edytuj (294 → 269) replicatei groupjest tak samo skutecznym sposobem zliczania farby, i zajmuje mniej kodu niż funkcja niestandardowas
  • Edycja (269 → 261) nie wymaga maxpołączenia
  • Edytuj (261 → 251), nie trzeba przerywać malowania 0 cali f

To jest zbyt wolne .
Alexandru

To jest golf golfowy, nie? W przypadku gry w golfa ograniczenia zwykle takie jak „rozsądny czas” oznaczają, że dla docelowego rozmiaru wejściowego nie może to zająć dni. Czy są jakieś kryteria, według których 37 sekund (czas drugiej odpowiedzi) jest w porządku, ale 44 sekundy są zbyt wolne? Mógłbym po prostu poświęcić swój czas na szybszy procesor, jeśli chcesz!
MtnViewMark

W takim przypadku powinno to potrwać kilka sekund * spowolnienie języka. Popraw mnie, jeśli się mylę, ale czy Haskell nie jest dużo szybszy od Pythona? (dlatego nie głosowałem za rozwiązaniem Keitha). Wprowadzono rozwiązanie brutalnej siły C, które trwało mniej więcej w tym samym czasie, co zgodnie z przepisami było niedozwolone.
Alexandru

Mierzona na tej samej maszynie, działa znacznie szybciej niż rozwiązanie Python. Rozwiązanie Python na mojej maszynie zajmuje 133,556 sekundy. Rozwiązanie Haskell jest 3 razy szybsze. Zauważ też, że to rozwiązanie Haskell nie jest rozwiązaniem „brutalnej siły” (przez co myślę, że masz na myśli po prostu budowanie szeregu kolorów na całej długości ściany).
MtnViewMark

0

Perl - 148 bajtów

Wygląda na to, że najlepiej grać w Perla. łatwe do kodowania krótsze i szybsze. ;)

kod:

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

czas:

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 znaków, 1,3 sekundy

Niestety musiałem wyciąć część standardową / wymaganą, która nie obsługuje JavaScript. Zamiast tego otrzymuję dane wejściowe z przesłanego pliku <input>(którego nie liczę w mojej liczbie znaków , chociaż prawdopodobnie powinienem).

Oto wersja bez golfa. Jest to funkcja, która pobiera pełny ciąg wejściowy ... wszystkie 14 MB! Ten zajmuje 1,3 sekundy; wersja golfowa zajmuje około dwa razy więcej - ale wciąż przewyższa inne rozwiązania! Co ciekawe, w Firefox jest dwa razy szybszy niż w Chrome. Demo na żywo tutaj .

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

A oto wersja golfowa.

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

zrzut ekranu

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.