การพิมพ์ชุดคณิตศาสตร์รัดกุมใน Raku


9

ชุดคณิตศาสตร์ใช้ตัวอย่างลำดับต่อเนื่องที่แสดงที่นี่เป็นอาร์เรย์:

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

พิมพ์:

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

a8 =  8
a9 =  9

คำถามของฉัน: 1- มีวิธีง่ายๆในการวางองค์ประกอบแรกเช่นa0 = 0จากผลลัพธ์ที่พิมพ์หรือไม่

2- รหัสนี้อาจจะทำให้สำนวนมากขึ้น?

ขอบคุณ.


@DanBron ขอบคุณสำหรับความคิดเห็น ฉันเพิ่งแก้ไขและทำรายละเอียดในโพสต์ต้นฉบับ
Lars Malmsteen

คำตอบ:


2

วิธีแก้ปัญหาแบร์โบน

เริ่มจากวิธีง่ายๆในการพิมพ์ลำดับของ มันไม่ได้เกี่ยวข้องกับข้อมูลเฉพาะที่คุณเพิ่มลงในคำถาม แต่เป็นจุดเริ่มต้นที่ดี:

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

ซึ่งแตกต่างจาก.kvที่แปลง invocant ของตนลงในแบบฟอร์มkey1, value1, key2, value2, key3, value3, ..., IE 6 องค์ประกอบถ้า invocant มันมี 3 องค์ประกอบ.pairsแปลง invocant key1 => value1, key2 => value2, key3 => value3, ...ของตนลงในแบบฟอร์ม

ฉันใช้.pairsแทน.kvบางส่วนเพราะมันหมายความว่าฉันสามารถใช้ใน».gistภายหลังในรหัสเพื่อให้ได้key1 => value1จอแสดงผลที่ดีสำหรับแต่ละองค์ประกอบ เราจะแก้ไขด้านล่าง แต่นี่เป็นจุดเริ่มต้นที่ดี

.headและ.tailสายเป็นวิธีที่เป็นสำนวนในการสร้างรายการเล็ก ๆ ขององค์ประกอบ N แรกและครั้งสุดท้ายจากรายการ invocant (ให้มันไม่ขี้เกียจ; เพิ่มเติมเกี่ยวกับว่าในเดือนก)

รับโซลูชันเริ่มต้นนี้say seq-range-gist (0,1 ... Inf)[^10]แสดง:

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

ถัดไปเราต้องการที่จะ "วางองค์ประกอบแรก ... จากผลลัพธ์ที่พิมพ์" say seq-range-gist (0,1 ... Inf)[1..9]แสดงน่าเสียดาย:

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

เราต้องการให้ตัวเลขทางด้านซ้ายของ=>เพื่อรักษาหมายเลขของลำดับเดิม ในการเปิดใช้งานสิ่งนี้เราแยกลำดับพื้นฐานออกจากช่วงที่เราต้องการแยกออกมา เราเพิ่มพารามิเตอร์ / อาร์กิวเมนต์ที่สอง@rangeและผนวก[@range]เข้ากับบรรทัดที่สองของ sub:

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

ตอนนี้เราสามารถเขียนsay seq-range-gist (0,1 ... Inf), 1..9เพื่อแสดง:

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

ในคำถามของคุณที่คุณใช้รูปแบบมากกว่าaINDEX = VALUE INDEX => VALUEในการอนุญาตให้ปรับแต่งส่วนสำคัญเราได้เพิ่ม&gistพารามิเตอร์ / อาร์กิวเมนต์ประจำตัวที่สามและเรียกใช้งานแทน.gistวิธีการที่มีอยู่แล้ว:

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

โปรดทราบว่าตอนนี้การเรียกใช้ "เมธอด" ในเนื้อความของseq-range-gistย่อยนั้น.&gistไม่ใช่.gistอย่างไร ไวยากรณ์.&fooจะเรียกย่อย &foo (ซึ่งถูกเรียกโดยการเขียนเพียงโดยทั่วไปfoo) ผ่าน invocant ทางด้านซ้ายของ.เป็น$_อาร์กิวเมนต์ย่อย

ยังทราบว่าฉันได้ทำพารามิเตอร์ชื่อหนึ่งโดยก่อนหน้านั้นด้วย&gist:

ดังนั้นตอนนี้say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }แสดง:

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

การเพิ่มเงา

ส่วนที่เหลือของคำตอบนี้เป็นวัสดุโบนัสสำหรับผู้อ่านที่สนใจเรื่องโปแลนด์

say seq-range-gist (0, 1, 2, 3), ^3 แสดง:

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

อุ่ย และแม้ว่าจะมีคู่มากกว่าส่วนหัวและหางรวมกันดังนั้นอย่างน้อยเราก็ไม่ได้เส้นที่ซ้ำกันมันก็ยังคงไม่มีจุดหมายโดยใช้head, ..., tailวิธีการเพื่อกำจัดองค์ประกอบเพียงหนึ่งหรือสองอย่าง มาเปลี่ยนคำสั่งสุดท้ายในเนื้อหาย่อยเพื่อกำจัดปัญหาเหล่านี้:

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

ถัดไปมันจะดีถ้าย่อยทำสิ่งที่มีประโยชน์ถ้าเรียกว่าไม่มีช่วงหรือส่วนสำคัญ เราสามารถแก้ไขได้โดยให้ค่าเริ่มต้น@rangeและ&gistพารามิเตอร์ที่เหมาะสม:

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

ถ้า@seqเป็นไม่ได้ ขี้เกียจแล้วเริ่มต้นที่เต็มรูปแบบของ@range @seqถ้า@seqเป็นอนันต์ (ซึ่งในกรณีนี้คือสันหลังยาว) แสดงว่าค่าเริ่มต้นสูงสุด 100ดี แต่ถ้าเกิดว่า@seqขี้เกียจ แต่ให้ผลน้อยกว่า 100 ค่าที่กำหนดล่ะ เพื่อให้ครอบคลุมกรณีนี้เราผนวก.grep: *.value.definedกับ@pairsประกาศ:

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

การปรับปรุงอย่างง่ายอื่น ๆ จะเป็นพารามิเตอร์ส่วนหัวและส่วนท้ายที่นำไปสู่วิธีแก้ไขปัญหาขั้นสุดท้าย

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

วิธีการแก้ปัญหาที่น้อยที่สุดทำงานได้ค่อนข้างดีและมันก็สำนวนที่เหมาะสม ในการแก้ปัญหาของฉันฉันต้องหันไปใช้ตัวแปร 'flag' เพื่อคำนวณด้วย...ส่วนที่ทำให้มันดูเหมือนโปรแกรม C ดังนั้นนี่คือคำตอบทั้งสองส่วนของคำถามของฉันจริง ๆ สำหรับโซลูชัน 'ที่ครอบคลุม' มันดูน่ากลัวไปหน่อย
Lars Malmsteen

ขอบคุณสำหรับความคิดเห็นของคุณและยอมรับคำตอบของฉัน @ LarsMalmsteen ที่กล่าวว่าฉันได้เขียนคำตอบของฉันใหม่ทั้งหมดและรู้สึกดีขึ้นมาก ฉันทิ้งโซลูชัน 'ที่ครอบคลุม' - ฉันไปไกลมากในวัชพืชด้วย! - แต่ฉันยังเขียนใหม่อย่างสมบูรณ์ "แก้ปัญหาน้อยที่สุด" และคำอธิบายประกอบ ฉันทำเพื่อผู้อ่านรายอื่นในภายหลังเป็นส่วนใหญ่ แต่คุณอาจได้รับประโยชน์จากการอ่านคำตอบใหม่
raiph

7

คุณสามารถข้ามค่า N แรกไปที่ใดก็ได้ IterableหรือSequenceด้วยskip:

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

หากคุณไม่ได้ระบุหมายเลขมันจะข้ามองค์ประกอบเดียวเท่านั้น


skipดูเหมือนว่าจะเอาแค่ ouput เช่นองค์ประกอบดัชนี 0 (A0) ยังคงอยู่ ฉันได้ลอง@seq:deleteแล้วมันจะแทนที่องค์ประกอบที่ 0 ด้วย(Any)
Lars Malmsteen

จริง skipเพียงแค่จะทำหน้าที่เป็นถ้าข้ามองค์ประกอบไม่อยู่ นี่อาจเป็นหรือไม่ใช่สิ่งที่คุณต้องการ :-)
Elizabeth Mattijsen

เมื่อฉันใส่เข้าไปskipในระหว่างเพื่อให้มันอ่าน: for @seq[^10].skip(0).kvมันไม่ข้ามองค์ประกอบที่ 0 อย่างแท้จริงและมันไม่สำคัญว่าถ้าฉันให้อาร์กิวเมนต์เป็นskip1 หรือ 2 มันก็บิดเบือนออกไปอีก ฉันต้องการวิธีการปฏิบัติเพื่อลบองค์ประกอบที่ 0 จากพื้นดินขึ้น
Lars Malmsteen

1
บางทีfor @seq[^10].kv.skip(2)สิ่งที่คุณกำลังมองหาคืออะไร?
Elizabeth Mattijsen

ใช่มันทำงานได้ดี ที่จริงฉันพยายามใส่skipหลัง.kvแต่ใช้ข้อโต้แย้งอื่นที่ไม่ใช่ 2 ดังนั้นจึงไม่ทำงาน ขอบคุณสำหรับการแก้ปัญหา
Lars Malmsteen

7

นี่อาจเป็นสำนวนที่ค่อนข้างมาก:

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

คุณไม่จำเป็นต้องใช้ตัวแปรศัพท์ภายในลำดับ; ตัวแปรตัวยึดตำแหน่งWhateverหรืออย่างใดอย่างหนึ่งสามารถนำมาใช้อย่างปลอดภัยภายในลำดับ จากนั้นคุณสามารถเลือกองค์ประกอบของลำดับที่คุณต้องการพิมพ์ ซึ่งผลตอบแทน«(0 1 2 3)(7 8 9 10)␤»


ขอบคุณสำหรับคำตอบ ตัวwhateverดำเนินการกำลังรีเฟรช แต่เอาต์พุตอนุกรม / ลำดับไม่ได้แก้ไขปัญหาหลัก ฉันต้องการที่จะพิมพ์ชุดตามที่พวกเขาเห็นในคณิตศาสตร์ texbooks เช่นมี...เครื่องหมายในระหว่าง
Lars Malmsteen

@ LarsMalmsteen โอเคฉันจะแก้ไขมัน
jjmerelo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.