O çitleri boya


9

Sen Tom Sawyer'sın ve 102400 m uzunluğunda bir çit boyamalısın. Neyse ki, arkadaşlarınız çeşitli şeyler karşılığında size yardımcı olmaya karar verdi. Her arkadaş S'den başlayarak C rengiyle L metre boyayacak . S , L tamsayı metre ve 1 ≤ C ≤ 97'dir. Sıkılmak, her rengin kaç metre olduğunu bulmaya karar verirsiniz.

Giriş

Giriş standart girişten okunur. Her satır, yukarıda tarif edildiği gibi üç sayı S , L , C içerir .

Çıkışı

Çıktı standart çıktıya yazılır. Son parmaklıkta görünen her renk için renk numarasını ve kaç kez göründüğünü yazdırın. Renklere göre sipariş verin.

Örnekler

Giriş 0

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

Çıkış 0

1 4
2 2
5 3

Giriş 1

 0 100 1
 50 150 2

Çıktı 1

 1 50
 2 150

Giriş 2

 500 1000 1
 0 2000 2

Çıktı 2

 2 2000

Daha fazla örnek

İşte küçük bir jeneratör:

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

Çalışan örnekler:

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

Programınızın makul bir sürede çalışması gerekir. Çözümüm son örnekte birkaç saniye içinde çalışıyor.

En kısa kod kazanır.

Son test için çalışma süresini ve çıktınızı ekleyin.

DÜZENLEME : Bu sorunun kaba zorlama olması amaçlanmamıştır, bu nedenle önemsiz bir çözüm kabul edilemez.


Bana en basit yolun (diziyi ayır, doldur, dizideki her rengin sayımını, çıktısını) makul bir sürede çalıştıracağını düşünüyorum. Görünüşe göre meydan okumaya bir algoritma getirmeyi düşünüyorsunuz - yanılıyor muyum?
Matthew

1000000 ops X 25000 ortalama uzunluk = 25 * 10 ^ 9'un makul bir süre içinde çalışmayacağını düşünüyordum. Aksini düşünürseniz çit uzunluğunu artırabilirim.
Alexandru

Ah, girdinin bir milyon satır olduğunu kaçırdım, kötüyüm.
Matthew

1
@Keith: ITYM İmparatorluk Birimleri : en.wikipedia.org/wiki/Imperial_units
Paul R

1
Keith: Sanırım bugün bir Tom Sawyer'ın çok daha mantıklı olacağını ve SI kullanacağını varsayabilirsiniz.
Joey

Yanıtlar:


2

Python, 221 239 karakter

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]

FÇitin mevcut durumunu temsil eden üçlü olmayan (koşu başlangıcı, koşu sonu, renk) listesi olarak tutar . Jeneratör üst boyalarındaki rasgele boyama büyük ölçüde oldukça sık aralıklarla oluştuğu için, bu liste asla çok uzun değildir (tipik olarak 15-40 aralığında).

1M örneğinde 37 saniye içinde çalışır.


G+=[(a,min(b,s),d)]*(a<s)bir satırda for döngüsünü almak için vb. kullanabilirsiniz
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)son dört satır üzerinden birkaç karakter kaydeder ve sihirli sayı 98 bilmek ihtiyacını ortadan kaldırır.

@Gareth: Bence aynı renk birden fazla aralıkta kullanılmışsa kopyaları basar. Orada bir yerde uniqification olması gerekir ...
Keith Randall

Haklısın: sorted(set(...))artık bir gelişme değil.

1

Haskell, 251 261 269 294 karakter

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

Bu konuda çok doğru bir şey yok, çünkü çok fazla zaman ve yığın gerektiriyor ... Ama doğru cevapları üretiyor:

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

  • Düzenle (294 → 269) replicateve groupboyayı saymanın etkili bir yoludur ve özel işlevden daha az kod alırs
  • Düzenle (269 → 261) maxaramaya gerek yok
  • Düzenle (261 → 251) Boyayı 0 f

Öyle çok yavaş .
Alexandru

Kod golfü, değil mi? Kod golf için, genellikle "makul zaman" gibi kısıtlamalar, hedef girdi boyutu için günler süremeyeceği anlamına gelir. 37 saniyenin (diğer cevap süresinin) iyi olduğu, ancak 44 saniyenin çok yavaş olduğu bazı kriterler var mı? İstersen daha hızlı bir CPU'da benimkini zamanlayabilirim!
MtnViewMark

Bu durumda birkaç saniye * dil yavaşlaması gerekir. Yanılıyorsam düzelt ama Haskell Python'dan daha hızlı değil mi? (bu yüzden Keith'in çözümüne oy vermedim). Aynı zamanda, kurallara göre izin verilmeyen bir C kaba kuvvet çözümü yayınlandı.
Alexandru

Aynı makinede ölçülen, bu mu daha hızlı Python çözümü daha çalıştırın. Python çözümü makinemde 133.556 saniye sürüyor. Haskell çözümü 3 kat daha hızlı. Ayrıca, bu Haskell çözümünün bir "kaba kuvvet" çözümü olmadığını unutmayın (bununla sadece duvarın uzunluğu boyunca bir renk dizisi oluşturmak anlamına geldiğini tahmin ediyorum.)
MtnViewMark

0

Perl - 148 bayt

Görünüşe göre Perl oynamak için en iyisi. daha kısa ve daha hızlı kodlama kolaydır. ;)

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

süresi:

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 karakter, 1.3 saniye

Ne yazık ki, JavaScript'in desteklemediği şartın stdin / out kısmını kesmek zorunda kaldım. Bunun yerine, bir dosya yüklemesinden girdiyi <input>alıyorum (muhtemelen yapmam gerekse de benim char sayımda saymıyorum).

İşte ungolfed versiyonu. Tam giriş dizesini alan bir işlev ... hepsi 14MB! 1.3 saniye süren budur; Golf versiyonu yaklaşık iki kat daha uzun sürüyor - ama yine de diğer çözümleri yeniyor! İlginç bir şekilde, Firefox'ta Chrome'dan iki kat daha hızlı. Burada canlı demo .

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

Ve işte golfçü versiyon.

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

ekran görüntüsü

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.