เกลียวการคูณที่ไม่ซ้ำกัน


13

คนนี้เป็นแรงบันดาลใจจากงานอดิเรกล่าสุดของเคลวินคูณท้าทายตาราง

เขียนฟังก์ชั่นหรือโปรแกรมที่ใช้จำนวนเต็มNเป็นอินพุตและพิมพ์หรือส่งกลับเกลียวหมุนคูณ N-by-N ที่ไม่ซ้ำกัน รหัสจะต้องทำงาน (ในทางทฤษฎี) สำหรับ N ระหว่าง 0 ถึง 1,000 (การส่งออกอาจเป็นเรื่องยาก) เอาต์พุตควรเทียบเท่ากับตารางที่สร้างโดยโพรซีเดอร์ต่อไปนี้:

  1. กรอกตารางการคูณ N-by-N เช่นสำหรับ N = 3:

    1 2 3
    2 4 6
    3 6 9
    
  2. หมุนวนตามเข็มนาฬิกาจากมุมซ้ายบนสังเกตตัวเลขที่คุณไป เมื่อคุณเยี่ยมชมหมายเลขที่คุณเคยเยี่ยมชมให้แทนที่ด้วย 0

ตัวอย่างบางส่วนอาจทำให้ชัดเจนยิ่งขึ้น:

n = 0:
0

n = 1:
1

n = 2:       //   Spiral order:
1  2         //   1  2
0  4         //   4  3

n = 3:
1  2  3      //   1  2  3
0  4  6      //   8  9  4
0  0  9      //   7  6  5

n = 4:
1  2  3  4   //   1   2   3   4
0  0  6  8   //  12  13  14   5
0  0  9 12   //  11  16  15   6
0  0  0 16   //  10   9   8   7

n = 5:
1   2   3   4   5
0   0   6   8  10
0   0   9  12  15
0   0   0  16  20
0   0   0   0  25

n = 10:
1   2   3   4   5   6   7   8   9  10
0   0   0   0   0  12  14  16  18  20
0   0   0   0  15   0  21  24  27  30
0   0   0   0   0   0  28  32  36  40
0   0   0   0  25   0  35   0  45  50
0   0   0   0   0   0  42  48  54  60
0   0   0   0   0   0  49  56  63  70
0   0   0   0   0   0   0  64  72  80
0   0   0   0   0   0   0   0  81  90
0   0   0   0   0   0   0   0   0 100

พบตัวเลขดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

รูปแบบเอาต์พุตที่สมเหตุสมผลใด ๆ ได้รับการยอมรับ แต่ต้องเป็นเมทริกซ์ N-by-N ซึ่งไม่สามารถเป็นเพียงรายการได้ รูปแบบดังกล่าวได้รับการยอมรับด้านล่างเนื่องจากมีคอลัมน์ที่ 1-by-N ที่แยกแยะได้ง่าย N หรือ N-by-1 แถว:

[[1 2 3][0 4 6][0 0 9]]   <-- OK

[[1 0 0][2 4 0][3 6 9]]   <-- OK

ans =                     <-- OK
    1  2  3
    0  4  6
    0  0  9   

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


ฉันสอดแนมด้วยตาตัวน้อยของฉันด้วยตะแกรงปรับระดับของ eratosthenes! ฉันค่อนข้างแน่ใจว่ามีรูปแบบที่คุณสามารถใช้ที่นี่ที่ฉันเคยเห็นที่ไหนสักแห่งหรืออย่างอื่น
Addison Crump

2
ทำไมจะมีผลลัพธ์สำหรับn=0ที่ไม่มีศูนย์ในตารางการคูณ ฉันสามารถเข้าใจn=1ผลลัพธ์ 1 ได้ แต่ทำไมถึงมีค่าเป็นศูนย์
Tom Carpenter

@ TomCarpenter อาจเป็นการตัดสินใจที่ไม่ดี แต่ฉันรู้ว่าจะมี "สิ่งที่เกี่ยวกับ N = 0?" - คำถามดังนั้นฉันจึงทำกฎ N = 0 -> 0 เมื่อมองย้อนกลับไปมันอาจจะดีกว่าที่จะบอกว่า N> 0 แต่มันก็สายเกินไปแล้วตอนนี้ฉันกลัว = /
Stewie Griffin

2
@StewieGriffin คุณบอกว่าผลลัพธ์จะต้องเป็นเมทริกซ์ N-by-N ดังนั้นผลลัพธ์สำหรับn=0ควรเป็นเมทริกซ์ 0 คูณ 0 หรือคำถามจะไม่สอดคล้องกัน
alephalpha

คำตอบ:



8

Mathematica 123 122 117 98 92 73 ไบต์

ด้วย 24 ไบต์ที่บันทึกไว้ต้องขอบคุณ LegionMammal978 และอีก 19 โดย alephalpha!


น่าแปลกที่ในตารางนี้อินสแตนซ์ของจำนวนเต็มใด ๆ หลายอินสแตนซ์nจะมีลำดับสัมพัทธ์เหมือนกันในรูปเกลียวเหมือนกับที่ทำในตาราง! การปรากฏตัวครั้งแรกของตัวเลขจะnอยู่ที่เซลล์มากโดยที่ตัวเลขนั้นจะปรากฏขึ้นเป็นครั้งแรกในตาราง (เมื่อมีคนกรอกข้อมูลในแถวตารางทีละแถว) ซึ่งหมายความว่าวิธีการนี้สามารถเพิกเฉยต่อข้อ จำกัด ของเกลียวทั้งหมดได้ (ดูคำอธิบายด้านล่าง)

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&

ตัวอย่าง

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&[10]

{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {0, 0, 0, 0, 0, 12, 14, 16, 18, 20}, {0, 0, 0, 0, 15, 0, 21, 24, 27, 30}, {0, 0, 0, 0, 0, 0, 28, 32, 36, 40}, {0, 0, 0, 0, 25, 0, 35, 0, 45, 50}, {0, 0, 0, 0, 0, 0, 0, 42, 48, 54, 60}, {0, 0, 0, 0, 0, 0, 0, 49, 56, 63, 70}, {0, 0, 0, 0, 0, 0, 0, 64, 72, 80}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 90}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}}


Grid[%]

TBLE


คำอธิบาย

เราใช้ประโยชน์จากความจริงที่ว่าคำสั่งหมุนวนของตำแหน่งของตัวเลขใด ๆ , n, เป็นเช่นเดียวกับคำสั่งของตำแหน่งแถวคอลัมที่กลับมาจากฟังก์ชั่นPositions!

สถานที่ตั้งของเกิดขึ้นครั้งแรกของแต่ละหมายเลข (ไม่ว่าจะเป็นหนึ่งในคำสั่งซื้อโดยเกลียวหรือโดยตำแหน่งตาราง) Positionจะเป็นองค์ประกอบแรกที่ส่งกลับโดย เซลล์ที่เกิดขึ้นครั้งแรกนั้นจะถูกทิ้งไว้ตามที่เป็น อินสแตนซ์ที่เหลืออยู่ของจำนวนจะถูกแทนที่ด้วย 0

ดู Let 's n==18ที่วิธีการทำงานนี้การตรวจสอบสำหรับกรณีของ แนวคิดคือเริ่มต้นด้วยตารางสูตรคูณ:

(t = Table[k Range@#, {k, #}] &[10]) // Grid

และค้นหาตำแหน่งแถวแถวของแต่ละหมายเลข ตัวอย่างเช่น 18 ตั้งอยู่ที่แถว 2, Col 9 (อินสแตนซ์แรก); แถว 3, Col 6; แถว 6 คอลัมน์ 3 และแถวที่ 9, คอลัมน์ที่ 2 มีตำแหน่งเป็นลำดับเกลียวที่เกี่ยวข้อง {44, 58, 68, 82}

Position[t, 18]

{{2, 9}, {3, 6}, {6, 3}, {9, 2}}

ดังตารางด้านล่าง

table2

อินสแตนซ์ 3 ตัวสุดท้ายของ 18 จะต้องถูกแทนที่ด้วย 0 (เราจะใช้ศูนย์สีฟ้าขนาดใหญ่ที่เป็นตัวหนาเพื่อให้พวกเขาสามารถเห็นได้อย่างง่ายดาย)

ReplacePart[%, {{3, 6}, {6, 3}, {9, 2}} -> Style[0, {Blue, Bold, 16}]]// Grid

table3


มีเหตุผลที่ไม่เขียนFunctionหรือไม่?
LegionMammal978

1
ฉันมีปัญหากับฟังก์ชั่นบริสุทธิ์แบบซ้อน แต่การวนซ้ำนี้ไม่ต้องการสิ่งนั้น ขอบคุณ
DavidC

ฉันนับ 117 ไบต์ไม่รวมบรรทัดใหม่
LegionMammal978


กอล์ฟเพิ่มเติม:ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&
alephalpha

2

Python, 99 95 90 89 87 81 ไบต์

รหัส Golfed:

n=range(1,input()+1);m=[]
for x in n:l=[(x*y,0)[x*y in m]for y in n];m+=l;print l

Ungolfed:

n=range(1,input()+1);
m=[]
for x in n:
  l=[(x*y,0)[x*y in m]for y in n];
  m+=l;
  print l

เอาท์พุท:

10 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
[0, 0, 0, 0, 0, 12, 14, 16, 18, 20]
[0, 0, 0, 0, 15, 0, 21, 24, 27, 30] 
[0, 0, 0, 0, 0, 0, 28, 32, 36, 40]
[0, 0, 0, 0, 25, 0, 35, 0, 45, 50] 
[0, 0, 0, 0, 0, 0, 42, 48, 54, 60]
[0, 0, 0, 0, 0, 0, 49, 56, 63, 70] 
[0, 0, 0, 0, 0, 0, 0, 64, 72, 80]
[0, 0, 0, 0, 0, 0, 0, 0, 81, 90] 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 100]

thanx @valuah สำหรับการป้อนข้อมูลไบต์โกน
CSᵠ

2

MATLAB, 96 88 87 86 79 ไบต์

นี่คือรหัส 79 ไบต์ซึ่งตามหลังผลลัพธ์ตัวอย่าง (สำหรับ n = 0 โดยเฉพาะ)

n=input('');m=+(n>0);for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

อันนี้คือ 75 ไบต์มีพฤติกรรมเดียวกันยกเว้น n = 0 ซึ่งจะสร้างอาร์เรย์ที่ว่างเปล่าตามความหมายของคำถาม (N โดย N array N = 0 0 0 = อาเรย์ว่าง)

n=input('');m=[];for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

สิ่งนี้ยังทำงานร่วมกับอ็อกเทฟ คุณสามารถลองออนไลน์ได้ที่นี่ รหัสถูกเพิ่มเป็นไฟล์ชื่อ 'multspiral.m' แล้ว ดังนั้นที่พรอมต์คู่พิมพ์multspiralและกด Enter จากนั้นคุณควรป้อนขนาดของตาราง (เช่น 4) ผลลัพธ์จะถูกพิมพ์


มันทำงานยังไง?

ก่อนนี้ใช้หมายเลขอินพุตตามต้องการ (เช่น 6, 4, ฯลฯ )

n=input('');

จากนั้นเราจัดการกับกรณีn=0และn=1- สิ่งเหล่านี้ได้รับการดูแลเป็นพิเศษเนื่องจากเป็นสองสิ่งที่ไม่ปฏิบัติตามกฎที่ฉันใช้ในการสร้างอาร์เรย์ - ในความเป็นจริงนี่อาจเป็น 5 ไบต์ที่สั้นกว่าหากไม่ใช่สำหรับn=0กรณีที่คลุมเครือ

m=+(n>0);

จากนั้นสำหรับค่าทั้งหมดn>2เราจะทำการวนลูปจนกว่าเมทริกซ์จะโตจนมีขนาดที่ถูกต้อง

for i=2:n;

มีจริงเพียงสามความแตกต่างระหว่างที่เรียบง่ายnและสำหรับทุกn+1 n>=2เหล่านี้คือ:

  1. n(1:n)คอลัมน์ใหม่จะถูกเพิ่มขวาสุดในอาร์เรย์ที่มีตัวเลข คำนวณได้อย่างง่ายดายด้วย:

     a=i*(1:i);
    
  2. องค์ประกอบใด ๆ ที่จะถูกเพิ่มในคอลัมน์ใหม่นั้นจะต้องถูกลบออกจากเมทริกซ์ที่มีอยู่ (ตั้งค่าเป็นศูนย์) เนื่องจากพวกมันจะมาในรูปแบบเกลียวในภายหลังมากกว่าคอลัมน์ใหม่ สิ่งนี้จะถูกลบออกโดยใช้การซ้อนสำหรับวนรอบเพื่อตั้งค่าองค์ประกอบทั้งหมดในเมทริกซ์ปัจจุบันซึ่งอยู่ในคอลัมน์ใหม่ให้เป็นศูนย์

    for j=a;
        m(m==j)=0;
    end;
    
  3. มีแถวล่างสุดใหม่ซึ่งทุกองค์ประกอบยกเว้นสิ่งที่อยู่ในคอลัมน์ใหม่จะเป็นศูนย์ เมื่อมีการเพิ่มคอลัมน์ใหม่เนื่องจากดัชนีไม่อยู่ในขอบเขตที่สร้างขึ้นโดยเจตนานั้นจะถูกเพิ่มเข้าไปโดยอัตโนมัติด้วย 0 หนึ่งในคุณสมบัติที่แข็งแกร่งของ MATLAB คือมันสามารถเติบโตอาร์เรย์โดยไม่มีการจัดการพิเศษใด ๆ ดังนั้นเราจึงสามารถเพิ่มแถวและคอลัมน์ใหม่ได้ง่ายๆ ด้วย:

    m(1:i,i)=a;
    

ในที่สุดเรามีจุดสิ้นสุดของการวนรอบ - ซึ่งเมื่อมาถึงเมทริกซ์จะmมีเอาต์พุตของเรา ในขณะที่คุณมีความยืดหยุ่นกับรูปแบบผลลัพธ์เมทริกซ์จะแสดงโดยเพียงแค่mขึ้นบรรทัดใหม่โดยไม่มีเครื่องหมายอัฒภาค

end;
m

ตัวอย่างเช่นถ้าเรารันโปรแกรมให้ป้อนหมายเลข 10 เราจะได้ผลลัพธ์ต่อไปนี้:

m =
     1     2     3     4     5     6     7     8     9    10
     0     0     0     0     0    12    14    16    18    20
     0     0     0     0    15     0    21    24    27    30
     0     0     0     0     0     0    28    32    36    40
     0     0     0     0    25     0    35     0    45    50
     0     0     0     0     0     0    42    48    54    60
     0     0     0     0     0     0    49    56    63    70
     0     0     0     0     0     0     0    64    72    80
     0     0     0     0     0     0     0     0    81    90
     0     0     0     0     0     0     0     0     0   100

1

Haskell, 103 99 ไบต์

import Data.Lists
f 0=[[0]]
f n=chunksOf n$foldr(\c d->c:replace[c][0]d)[][a*b|a<-[1..n],b<-[1..n]]

ตัวอย่างการใช้งาน: ->f 4[[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]]

ฉันได้ค้นพบเพียงData.Listsโมดูลที่มีฟังก์ชั่นที่ดีในรายการ (เช่นreplace) และการส่งออกอีกครั้งData.List, และData.List.SplitData.List.Extras


1

Ruby, 67 63 61 ไบต์

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}

63 ไบต์

->n{s,x=1..n,{};s.map{|c|s.map{|r|e=x[v=c*r]==1?0:v;x[v]=1;e}}}

67 ไบต์

->n{s,x=1..n,[];s.map{|c|s.map{|r|e=x.include?(v=c*r)?0:v;x<<v;e}}}

การใช้งาน:

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}[10]
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 0, 0, 0, 0, 12, 14, 16, 18, 20], [0, 0, 0, 0, 15, 0, 21, 24, 27, 30], [0, 0, 0, 0, 0, 0, 28, 32, 36, 40], [0, 0, 0, 0, 25, 0, 35, 0, 45, 50], [0, 0, 0, 0, 0, 0, 42, 48, 54, 60], [0, 0, 0, 0, 0, 0, 49, 56, 63, 70], [0, 0, 0, 0, 0, 0, 0, 64, 72, 80], [0, 0, 0, 0, 0, 0, 0, 0, 81, 90], [0, 0, 0, 0, 0, 0, 0, 0, 0, 100]]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.