In sê-ri toán học chính xác trong Raku


9

Chuỗi toán học, ví dụ chuỗi liên tiếp được biểu diễn ở đây dưới dạng một mảng:

my @seq = my $a=0, {++$a} ... *;
for @seq[^10].kv {state $f=0; ($^k < 4 or $^k > 7) ?? say "a$^k =  "  ~ $^v !! (say "..." if $f ne 1; $f=1) };

Bản in:

a0 =  0
a1 =  1
a2 =  2
...

a8 =  8
a9 =  9

Câu hỏi của tôi: 1- Có cách nào đơn giản để bỏ chỉ phần tử đầu tiên tức là a0 = 0từ đầu ra được in không?

2- Mã này có thể được thực hiện nhiều hơn?

Cảm ơn bạn.


@DanBron Cảm ơn bạn đã bình luận. Tôi vừa mới chỉnh sửa và xây dựng trên bài viết gốc.
Lars Malmsteen

Câu trả lời:


2

Một giải pháp barebones

Hãy bắt đầu với một giải pháp rất đơn giản để in một ý chính của trình tự. Nó không giải quyết các chi tiết cụ thể mà bạn đã thêm vào câu hỏi của mình nhưng đó là điểm khởi đầu tốt:

sub seq-range-gist ( @seq ) {
  my @pairs = @seq.pairs;
  join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}

Không giống như .kv, chuyển đổi invocant của nó thành dạng key1, value1, key2, value2, key3, value3, ..., tức là 6 phần tử nếu invocant của nó chứa 3 phần tử, .pairschuyển đổi invocant của nó thành dạng key1 => value1, key2 => value2, key3 => value3, ....

Tôi đã sử dụng .pairsthay vì .kvmột phần vì điều đó có nghĩa là tôi chỉ có thể sử dụng ».gistsau này trong mã để dễ dàng có được một key1 => value1màn hình đẹp cho từng thành phần. Chúng tôi sẽ sửa đổi điều đó dưới đây nhưng đây là một khởi đầu thành ngữ tốt.

Các cuộc gọi .headvà cách .tailgọi là cách thành ngữ để tạo danh sách nhỏ các thành phần N đầu tiên và cuối cùng từ một danh sách bất khả xâm phạm (miễn là nó không lười biếng; nói thêm về điều đó trong một mo).

Đưa ra giải pháp ban đầu này, say seq-range-gist (0,1 ... Inf)[^10]hiển thị:

0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9

Tiếp theo, chúng tôi muốn có thể "chỉ bỏ phần tử đầu tiên ... từ đầu ra được in". Thật không may say seq-range-gist (0,1 ... Inf)[1..9]hiển thị:

0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9

Chúng tôi muốn số ở bên trái của số =>để giữ lại số thứ tự của chuỗi ban đầu. Để cho phép điều này, chúng tôi chia chuỗi bên dưới khỏi phạm vi mà chúng tôi muốn trích xuất. Chúng tôi thêm một tham số / đối số thứ hai @rangevà nối [@range]vào dòng thứ hai của phụ:

sub seq-range-gist ( @seq, @range ) {
  my @pairs = @seq.pairs[@range];

Bây giờ chúng ta có thể viết say seq-range-gist (0,1 ... Inf), 1..9để hiển thị:

1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9

Trong câu hỏi của bạn, bạn đã sử dụng định dạng aINDEX = VALUEchứ không phải INDEX => VALUE. Để cho phép tùy chỉnh ý chính, chúng ta thêm một &gisttham số / tham số thường trình thứ ba và gọi nó thay vì .gistphương thức dựng sẵn :

sub seq-range-gist ( @seq, @range, :&gist ) {
  my @pairs = @seq.pairs[@range];
  join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}

Lưu ý làm thế nào các cách gọi "phương thức" trong cơ thể của seq-range-gistphụ bây giờ .&gist, không .gist. Cú pháp .&foogọi một phụ &foo (thường được gọi bằng cách chỉ viết foo), truyền vào bên trong của bên trái .dưới dạng một$_ đối số đối số cho phụ.

Cũng lưu ý rằng tôi đã tạo &gisttham số được đặt tên bằng cách đặt trước tham số đó bằng a :.

Vì vậy, bây giờ say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }hiển thị:

a1 =  1
a2 =  2
a3 =  3
...
a8 =  8
a9 =  9

Thêm đánh bóng

Phần còn lại của câu trả lời này là tài liệu thưởng cho những độc giả quan tâm đến việc đánh bóng.

say seq-range-gist (0, 1, 2, 3), ^3 hiển thị:

0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2

Giáo sư. Và ngay cả khi có nhiều cặp hơn đầu và đuôi kết hợp, do đó, ít nhất chúng tôi đã không nhận được các dòng lặp đi lặp lại, vẫn sẽ vô nghĩa khi sử dụng head, ..., tailphương pháp tiếp cận chỉ với một hoặc hai yếu tố. Hãy thay đổi tuyên bố cuối cùng trong cơ thể phụ để loại bỏ các vấn đề sau:

  join "\n",
    @pairs < $head + $tail + 3   # Of course, the 3 is a bit arbitrary
      ?? @pairs».&gist
      !! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)

Tiếp theo, sẽ thật tuyệt nếu phụ làm điều gì đó hữu ích nếu được gọi mà không có phạm vi hoặc ý chính. Chúng tôi chủ yếu có thể khắc phục điều đó bằng cách đưa ra @range&gistcác tham số phù hợp mặc định:

sub seq-range-gist (
  @seq,
  @range = @seq.is-lazy ?? ^100 !! ^@seq,
  :&gist = { .gist }
) {

Nếu @seqkhông lười biếng , sau đó @rangemặc định là đầy đủ các @seq. Nếu @seqvô hạn (trong trường hợp đó cũng là lười biếng), thì mặc định tối đa 100 là ổn. Nhưng nếu @seqlười biếng nhưng mang lại ít hơn 100 giá trị được xác định thì sao? Để bao gồm trường hợp này, chúng tôi thêm .grep: *.value.definedvào @pairstuyên bố:

  my @pairs = @seq.pairs[@range].grep: *.value.defined;

Một cải tiến đơn giản khác sẽ là các tham số đầu và đuôi tùy chọn, dẫn đến một giải pháp đánh bóng cuối cùng:

sub seq-range-gist (
  @seq,
  @range = @seq.is-lazy ?? ^100 !! ^@seq,
  :$head = 3,
  :$tail = 2,
  :&gist = { .gist }
) {
  my @pairs = @seq.pairs[@range].grep: *.value.defined;
  join "\n",
    @pairs <= $head + $tail + 2
      ?? @pairs».&gist
      !! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
}

Giải pháp tối thiểu hoạt động khá tốt và nó cũng hoàn toàn thành ngữ. Trong giải pháp của mình, tôi đã phải dùng đến một biến 'cờ' để tính toán với ...phần khiến nó trông giống như một chương trình C. Vì vậy, điều này trả lời cả hai phần của câu hỏi của tôi, thực sự. Đối với giải pháp 'toàn diện', nó có vẻ hơi đáng sợ, thực sự.
Lars Malmsteen

Cảm ơn phản hồi của bạn và chấp nhận câu trả lời của tôi @LarsMalmsteen. Điều đó nói rằng, tôi đã hoàn toàn viết lại câu trả lời của mình và cảm thấy nó tốt hơn nhiều. Tôi đã bỏ giải pháp 'toàn diện' - Tôi đã đi xa vào đám cỏ dại với điều đó! - nhưng tôi cũng đã viết lại hoàn toàn "giải pháp tối thiểu" và giải thích kèm theo. Tôi đã làm như vậy chủ yếu cho các độc giả khác sau này nhưng bạn có thể nhận được một số giá trị từ việc đọc câu trả lời mới.
raiph

7

Bạn có thể bỏ qua các giá trị N đầu tiên trên bất kỳ Iterable hoặc Sequencevới skip:

for (^5).skip(3) {
    .say
}
# 3
# 4

Nếu bạn không chỉ định một số, nó sẽ chỉ bỏ qua một yếu tố.


Các skipdường như loại bỏ chỉ ouput tức là phần tử với chỉ số 0 (a0) vẫn còn. Tôi đã thử @seq:deletevà nó chỉ thay thế phần tử thứ 0 bằng(Any)
Lars Malmsteen

Thật. Ý skipchí chỉ hành động như thể các yếu tố bị bỏ qua không tồn tại. Điều này có thể hoặc không thể là những gì bạn muốn :-)
Elizabeth Mattijsen

Khi tôi đặt skipở giữa để nó đọc: for @seq[^10].skip(0).kvthực sự không bỏ qua phần tử thứ 0 và nó không thành vấn đề nếu tôi đưa ra làm đối số cho skip1 hoặc 2, nó chỉ làm biến dạng thêm nữa. Tôi cần một cách thực tế để loại bỏ phần tử thứ 0 từ dưới lên.
Lars Malmsteen

1
Có lẽ đó for @seq[^10].kv.skip(2)là những gì bạn đang tìm kiếm?
Elizabeth Mattijsen

Vâng, đó là công việc. Trên thực tế, tôi đã cố gắng đặt skipsau .kvnhưng sử dụng các đối số khác 2, vì vậy nó không hoạt động. Cảm ơn bạn cho giải pháp.
Lars Malmsteen

7

Điều này có thể là một chút thành ngữ:

my @seq = 0, *+1 ... *;
say @seq[^4], @seq[7..10]

Bạn không cần sử dụng biến từ vựng trong chuỗi; một trong hai Whateverhoặc biến giữ chỗ một cách an toàn có thể được sử dụng trong chuỗi. Sau đó, bạn có thể chỉ cần chọn các yếu tố của chuỗi bạn muốn in. Trả về«(0 1 2 3)(7 8 9 10)␤»


Cảm ơn bạn đã trả lời. Các whatevernhà điều hành được refreshening nhưng sản lượng hàng loạt / chuỗi không đề cập đến vấn đề chính. Tôi muốn in sê-ri như chúng được thấy trên các sách toán học, tức là có ...ký hiệu ở giữa.
Lars Malmsteen

@LarsMalmsteen, OK, tôi sẽ chỉnh sửa nó
jjmerelo
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.