Vẽ hàng rào


9

Bạn là Tom Sawyer và bạn phải vẽ một hàng rào dài 102400 m. May mắn thay, bạn bè của bạn quyết định giúp bạn trao đổi những thứ khác nhau. Mỗi bạn sẽ vẽ L mét, bắt đầu từ S với màu C . S , L là số nguyên của mét và 1 ≤ C 97. Bạn cảm thấy buồn chán khi quyết định tìm hiểu xem bạn có bao nhiêu mét mỗi màu.

Đầu vào

Đầu vào được đọc từ đầu vào tiêu chuẩn. Mỗi dòng chứa ba số S , L , C như mô tả ở trên.

Ouput

Đầu ra được ghi vào đầu ra tiêu chuẩn. Đối với mỗi màu xuất hiện trên hàng rào cuối cùng, hãy in số màu và số lần nó xuất hiện. Sắp xếp theo màu sắc.

Ví dụ

Đầu vào 0

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

Đầu ra 0

1 4
2 2
5 3

Đầu vào 1

 0 100 1
 50 150 2

Đầu ra 1

 1 50
 2 150

Đầu vào 2

 500 1000 1
 0 2000 2

Đầu ra 2

 2 2000

Thêm ví dụ

Đây là một máy phát điện nhỏ:

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

Chạy ví dụ:

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

Chương trình của bạn phải chạy trong thời gian hợp lý. Giải pháp của tôi chạy trong vài giây trên ví dụ cuối cùng.

Mã ngắn nhất sẽ thắng.

Bao gồm thời gian chạy và đầu ra của bạn cho bài kiểm tra cuối cùng.

EDIT : Vấn đề này không có ý định bị ép buộc, vì vậy một giải pháp tầm thường không được chấp nhận.


Dường như với tôi rằng cách đơn giản nhất (phân bổ mảng, điền vào nó, đếm # của mỗi màu trong mảng, đầu ra) sẽ chạy trong một thời gian hợp lý. Có vẻ như bạn dự định đưa ra một thuật toán là một phần của thử thách, mặc dù vậy - tôi có sai không?
Matthew Đọc

Tôi đã nghĩ rằng 1000000 ops X 25000 chiều dài trung bình = 25 * 10 ^ 9 sẽ không chạy trong thời gian hợp lý. Tôi có thể tăng chiều dài hàng rào nếu bạn nghĩ khác.
Alexandru

Ah, tôi đã bỏ lỡ rằng đầu vào là một triệu dòng, xấu của tôi.
Matthew Đọc

1
@Keith: Đơn vị hoàng gia ITYM : en.wikipedia.org/wiki/Imperial_units
Paul R

1
Keith: Tôi nghĩ rằng bạn có thể cho rằng một Tom Sawyer ngày nay sẽ hợp lý hơn nhiều và sử dụng SI.
Joey

Câu trả lời:


2

Python, 221 239 ký tự

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]

Giữ Fnhư một danh sách các bộ ba không có thứ tự (bắt đầu chạy, kết thúc chạy, màu sắc) đại diện cho trạng thái hiện tại của hàng rào. Do bức tranh ngẫu nhiên trong máy phát điện vượt quá số lượng khá lớn, nên danh sách này không bao giờ quá dài (thường là trong phạm vi 15-40).

Chạy trong 37 giây trên ví dụ 1M.


bạn có thể sử dụng, G+=[(a,min(b,s),d)]*(a<s)v.v. để có được vòng lặp for trên một dòng
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)lưu một vài ký tự trong bốn dòng cuối cùng của bạn và tránh sự cần thiết phải biết số ma thuật 98.

@Gareth: Tôi nghĩ rằng sẽ in các bản sao nếu cùng một màu được sử dụng bởi nhiều hơn một phạm vi. Cần phải có sự thống nhất trong đó ở đâu đó ...
Keith Randall

Bạn nói đúng: nó sẽ cần phải được sorted(set(...))mà không còn một sự cải tiến.

1

Haskell, 251 261 269 294 ký tự

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

Một cái gì đó không hoàn toàn đúng về điều này vì nó tốn quá nhiều thời gian và chồng chất ... Nhưng nó tạo ra câu trả lời đúng:

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

  • Chỉnh sửa (294 → 269) replicategrouplà cách hiệu quả để đếm sơn và mất ít mã hơn chức năng tùy chỉnhs
  • Chỉnh sửa (269 → 261) không cần maxgọi
  • Chỉnh sửa (261 → 251) không cần phải loại bỏ sơn 0 trong f

Đó là quá chậm .
Alexandru

Đó là môn đánh gôn, không? Đối với môn đánh gôn, thông thường các hạn chế như "thời gian hợp lý" có nghĩa là, đối với kích thước đầu vào mục tiêu, không thể mất nhiều ngày. Có một số tiêu chí theo đó 37 giây (thời gian của câu trả lời khác) là ổn, nhưng 44 giây là quá chậm? Tôi chỉ có thể khai thác thời gian trên CPU nhanh hơn nếu bạn muốn!
MtnViewMark

Trong trường hợp này, sẽ mất vài giây * làm chậm ngôn ngữ. Chỉnh sửa cho tôi nếu tôi sai, nhưng không phải Haskell nhanh hơn Python nhiều? (đó là lý do tại sao tôi không bỏ phiếu cho giải pháp của Keith). Có một giải pháp vũ lực C được đăng tải mất khoảng thời gian đó, theo quy định, không được phép.
Alexandru

Đo trên cùng một máy, nó không chạy nhanh hơn nhiều so với các giải pháp Python. Giải pháp Python mất 133.556 giây trên máy của tôi. Giải pháp Haskell nhanh hơn gấp 3 lần. Ngoài ra, lưu ý rằng giải pháp Haskell này không phải là giải pháp "vũ phu" (theo đó tôi đoán bạn chỉ đơn giản là xây dựng một mảng màu theo chiều dài của bức tường.)
MtnViewMark

0

Perl - 148 byte

Có vẻ như Perl là tốt nhất để chơi với. dễ dàng để mã ngắn hơn và nhanh hơn. ;)

mã:

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

thời gian:

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 ký tự, 1,3 giây

Đáng buồn thay, tôi đã phải cắt bỏ phần stdin / out của yêu cầu, mà JavaScript không hỗ trợ. Thay vào đó, tôi nhận được đầu vào từ một tệp tải lên <input>thay vào đó (mà tôi không tính vào số char của mình, mặc dù tôi có lẽ nên làm vậy).

Đây là phiên bản vô văn hóa. Đây là một hàm có chuỗi đầu vào đầy đủ ... tất cả 14 MB của nó! Đây là cái mất 1,3 giây; phiên bản chơi gôn mất khoảng gấp đôi thời gian - nhưng nó vẫn vượt qua các giải pháp khác! Thật thú vị, nó nhanh gấp hai lần trong Firefox so với Chrome. Bản demo trực tiếp tại đây .

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

Và đây là phiên bản chơi gôn.

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

ảnh chụp màn hình

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.