Mở rộng các tab (triển khai mở rộng (1))


10

Nhiệm vụ của bạn lần này là triển khai một biến thể của expand(1)tiện ích POSIX mở rộng các tab thành không gian.

Chương trình của bạn là lấy một đặc tả tabstop và sau đó đọc đầu vào trên tiêu chuẩn và thay thế các ký tự tab trong đầu vào với số lượng khoảng trống thích hợp để đạt được điểm dừng tiếp theo. Kết quả nên được viết theo tiêu chuẩn .

Đặc điểm kỹ thuật Tabstop

Một đặc tả tabstop bao gồm một số duy nhất hoặc một danh sách các tabstops được phân tách bằng dấu phẩy. Trong trường hợp một số duy nhất, nó được lặp lại như thể bội số của nó xảy ra trong một danh sách được phân tách bằng dấu phẩy (nghĩa là 4đóng vai trò 4,8,12,16,20,...). Mỗi mục trong danh sách được phân tách bằng dấu phẩy là một số nguyên dương tùy ý có tiền tố là a +. Một +tiền tố chỉ ra sự khác biệt tương đối so với giá trị trước đó trong danh sách được phân tách bằng dấu phẩy. Giá trị đầu tiên trong danh sách phải là tuyệt đối (tức là không được trộn). Các tab tab xác định cột của ký tự không phải không gian tiếp theo (theo tab được mở rộng), với cột ngoài cùng bên trái được lấy là số 0. Các tab phải luôn mở rộng đến ít nhất một khoảng trắng.

Đầu ra đầu vào

Đặc tả tabstop sẽ được lấy làm tham số dòng lệnh đầu tiên cho chương trình hoặc đọc từ tiêu chuẩn dưới dạng dòng đầu tiên (kết thúc bởi một dòng mới), theo ý của bạn. Sau khi đọc tabstop, đầu vào còn lại (tất cả đầu vào, trong trường hợp trước) cho đến khi EOF được xử lý và mở rộng. Đầu ra mở rộng sẽ được viết theo tiêu chuẩn.

Tất cả các tab được mở rộng và tất cả các đầu vào, được giả định là tối đa 80 cột rộng. Tất cả các tabstops mở rộng đang tăng nghiêm ngặt.


Thí dụ

Đặc tả Tabstop 4,6,+2,+8tương đương với 4,6,8,16và với cả đầu vào

ab<Tab>c
<Tab><Tab>d<Tab>e<Tab>f

được mở rộng thành ( chỉ ra một khoảng trắng)

ab␣␣c
␣␣␣␣␣␣d␣e␣␣␣␣␣␣␣f

01234567890123456   (Ruler for the above, not part of the output)
          1111111

Ghi điểm là thuần túy ; mã ngắn nhất thắng.

Câu trả lời:


2

GolfScript ( 77 75 ký tự)

n/(','/{'+'/{~t++}*~:t}%81,{t*}%+:T;{[0\{.9={;T{1$>}?(.)@-' '*}*\)}/;]n+}/;

Tôi khá hài lòng với phân tích cú pháp tabspec.

# Split on commas
','/
# For each element:
{
    # Split on '+'
    '+'/
    # We now have either ["val"] or ["" "val"]
    # The clever bit: fold
    # Folding a block over a one-element array gives that element, so ["val"] => "val"
    # Folding a block over a two-element array puts both elements on the stack and executes,
    # so ["" "val"]{~t++}* evaluates as
    #     "" "val" ~t++
    # which evaluates val, adds the previous value, and concatenates with that empty string
    {~t++}*
    # Either way we now have a string containing one value. Eval it and assign to t
    ~:t
}%

Sau đó, tôi thêm bội số của phần tử cuối cùng cho đến khi tôi được đảm bảo có đủ để đạt đến cuối của 80 cột:

81,{t*}%+

Điều này mang lại hành vi mong muốn khi chỉ có một tabstop được chỉ định và mặt khác chỉ có liên quan trong trường hợp thông số kỹ thuật không đề cập. (NB nó làm cho danh sách các điểm dừng tab trở về 0 và sau đó lặp lại phần tử được phân tích cú pháp cuối cùng, nhưng điều đó không liên quan vì khi sử dụng danh sách tôi tìm phần tử đầu tiên lớn hơn vị trí hiện tại).

Phần còn lại là khá đơn giản.


2

Ruby 161 145

Đọc đặc tả tabstop trên dòng đầu tiên.

i=t=[]
gets.scan(/(\+)?(\d+)/){t<<i=$2.to_i+($1?i:0)}
81.times{|j|t<<j*i}
while gets
$_.sub!$&," "*(t.find{|s|s>i=$`.size}-i)while~/\t/
print
end

chỉnh sửa: Đã thêm hai dòng làm cho lần đọc tabstop cuối cùng lặp lại để thông số kỹ thuật tabstop của một số cũng hoạt động chính xác

ilà một biến tạm thời để giữ tabstop được phân tích cú pháp cuối cùng. tlà danh sách các tabstobs, được phân tích cú pháp từ gets.scandòng. Để có biện pháp tốt, chúng tôi thêm 81 bội số của tabstop được phân tích cú pháp cuối cùng. các while getsvòng lặp tiếp tục đi cho đến khi không có đầu vào nhiều hơn nữa. Đối với mỗi dòng đầu vào, chúng tôi thay thế các tab cho khoảng trắng, một tab tại thời điểm đó vì chuỗi di chuyển khi chúng tôi thêm khoảng trắng và chúng tôi phải tính toán lại điểm dừng chính xác.


Tôi không thực sự biết Ruby, nhưng bạn có thể viết x+($1?i:0)ngắn hơn không$1?x+i:x không?
Timwi

@Timwi Không! Ruby là một chút lạ với các nhà điều hành ternary. Thông thường bạn cần đặt một khoảng trắng ở đó ở đâu đó, bởi vì dấu hai chấm ( :) cũng có thể đánh dấu sự bắt đầu của một biểu tượng , nhưng vì một biểu tượng không thể bắt đầu bằng một chữ số,:0 không có khoảng trắng. Hoặc một cái gì đó. Thật lạ. Các dấu ngoặc đơn cũng rất quan trọng.
daniero

Đó là quét tabstop trông có lỗi với tôi. Trong t<<x+($1?i:0);i=xtuyên bố đầu tiên không thay đổi x, phải không? Tôi nghĩ bạn cần đảo ngược nó nhưi=x+($1?i:0);t<<i
Peter Taylor

1
Trong thực tế, bạn có thể lưu 16 bằng cách thay thế hai dòng đầu tiên bằng i=t=[](vì iđược đảm bảo không cần thiết trong lần đầu tiên); đơn giản hóa phân tích cú pháp dừng tab {t<<i=$2.to_i+($1?i:0)}và loại bỏ lhoàn toàn ( iđã giữ giá trị đó). Nhưng một điều tuyệt vời là không quan tâm đến việc tab ngừng tăng nghiêm ngặt: giúp bạn tiết kiệm được 4 ký tự và tôi có thể mượn nó để tiết kiệm 2.
Peter Taylor

@PeterTaylor Cảm ơn bạn đã nhập! Đó không phải là lỗi trực tiếp, nhưng chắc chắn là hơi bực bội. Tôi thấy quá dễ dàng để nhìn chằm chằm vào bản thân mình về mã như thế này.
daniero

1

C, 228 ký tự

Đây là một giải pháp C để bắt đầu mọi thứ. Vẫn còn rất nhiều việc phải chơi golf ở đây (nhìn vào tất cả những người đóif s và fors và putchars ...). Đã thử nghiệm với ví dụ thử nghiệm, cũng như với cùng một đầu vào nhưng 48cho thông số tab.

S[99],i;L,C;main(v){for(v=1;v;)v=scanf("+%d",&C),v=v>0?C+=L:scanf("%d",&C),
v&&(S[L=C]=++i,getchar());for(;i==1&&C<80;)S[C+=L]=1;for(C=L=0;C=~getchar();)
if(C+10)putchar(~C),L+=C+11?1:-L;else for(putchar(32);!S[++L];)putchar(32);}
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.