Vòng xoắn nhân


13

Điều này được lấy cảm hứng từ thử thách bảng nhân gần đây của Calvin .

Viết hàm hoặc chương trình lấy số nguyên Nlàm đầu vào và in hoặc trả về vòng xoắn nhân duy nhất N-by-N. Mã phải (về lý thuyết) làm việc cho N trong khoảng từ 0 đến 1000 (việc xuất ra điều này có thể khó khăn). Đầu ra phải tương đương với bảng được tạo bởi quy trình sau:

  1. Điền vào bảng nhân N-by-N. Ví dụ: N = 3:

    1 2 3
    2 4 6
    3 6 9
    
  2. Theo một vòng xoắn ốc theo chiều kim đồng hồ từ góc trên bên trái, lưu ý các số mà bạn truy cập. Khi bạn truy cập một số mà bạn đã truy cập, thay thế nó bằng 0.

Một vài ví dụ có thể làm cho nó rõ ràng hơn:

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

Các số được tìm thấy như thế này:

nhập mô tả hình ảnh ở đây

Bất kỳ định dạng đầu ra hợp lý nào đều được chấp nhận, nhưng nó phải là ma trận N-by-N, nó không thể chỉ là một danh sách. Các định dạng như vậy dưới đây được chấp nhận, vì có N cột 1-N dễ phân biệt hoặc hàng 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   

Mã ngắn nhất trong byte thắng.


Tôi theo dõi bằng con mắt nhỏ của mình một cái rây đã được sửa đổi! Tôi khá chắc chắn rằng có một mẫu bạn có thể sử dụng ở đây mà tôi đã thấy ở đâu đó hoặc khác.
Addison Crump

2
Tại sao sẽ có một đầu ra cho n=0nơi không có số 0 trong các bảng nhân. Tôi có thể hiểu n=1đầu ra 1, nhưng tại sao lại bao gồm 0?
Tom Carpenter

@TomCarpenter, nó có thể là một quyết định tồi, nhưng tôi biết sẽ có câu hỏi "Thế còn N = 0?", Vì vậy tôi đã đưa ra quy tắc N = 0 -> 0. Nhìn lại, có lẽ tốt hơn là nói rằng N> 0, nhưng bây giờ đã quá muộn rồi Tôi sợ = /
Stewie Griffin

2
@StewieGriffin Bạn nói rằng đầu ra phải là ma trận N-by-N, vì vậy đầu ra n=0phải là ma trận 0-by-0, hoặc câu hỏi sẽ không nhất quán.
alephalpha

Câu trả lời:


3

J, 22 byte

,~$[:(*~:)[:,1*/~@:+i.

Nó tạo ra ma trận 0-by-0 cho n=0.


8

Toán học 123 122 117 98 92 73 byte

Với 24 byte được lưu nhờ vào LegionMammal978 và 19 byte khác bởi alephalpha!


Đáng ngạc nhiên, trong bảng này, nhiều trường hợp của bất kỳ số nào nsẽ có cùng thứ tự tương đối trong vòng xoắn ốc giống như chúng làm trong chính bảng! Sự xuất hiện đầu tiên của một số nnằm ở chính ô nơi số đó xuất hiện đầu tiên trong bảng (khi một số lấp đầy trong hàng theo từng hàng). Điều này có nghĩa là cách tiếp cận có thể bỏ qua các ràng buộc xoắn ốc hoàn toàn, vì nó không có liên quan đến kết quả. (Xem giải thích bên dưới.)

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

Thí dụ

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


Grid[%]

khó khăn


Giải trình

Chúng tôi khai thác thực tế là thứ tự xoắn ốc của các vị trí của bất kỳ chữ số nào, n, giống như thứ tự của các vị trí hàng-col được trả về bởi hàm , Positions!

Vị trí xuất hiện đầu tiên của mỗi số (cho dù một đơn đặt hàng theo hình xoắn ốc hoặc theo vị trí bảng) sẽ là phần tử đầu tiên được trả về Position. Đó là tế bào xuất hiện đầu tiên sẽ được để lại như nó là. Các trường hợp còn lại của số được thay thế bằng 0.

Chúng ta hãy xem làm thế nào điều này hoạt động, kiểm tra cho trường hợp n==18. Ý tưởng là bắt đầu với bảng nhân:

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

và xác định vị trí hàng-col của mỗi số. Ví dụ: 18 được đặt tại Hàng 2, Col 9 (ví dụ đầu tiên); Hàng 3, Col 6; Hàng 6, Col 3; và Hàng 9, Col 2. Chúng có các vị trí theo thứ tự xoắn ốc tương ứng {44, 58, 68, 82}.

Position[t, 18]

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

như bảng dưới đây cho thấy.

ban 2

3 trường hợp cuối cùng của 18 cần phải được thay thế bằng 0. (Chúng tôi sẽ sử dụng một số 0 lớn màu xanh đậm để có thể dễ dàng phát hiện ra.)

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

bàn số 3


Có một lý do cho việc không viết một Function?
LegionMammal978

1
Tôi đã gặp rắc rối với các hàm thuần túy lồng nhau, nhưng phép lặp này không yêu cầu điều đó. cảm ơn.
DavidC

Tôi đếm 117 byte không bao gồm dòng mới.
LegionMammal978


Một số sân gôn khác:ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&
alephalpha

2

Python, 99 95 90 89 87 81 byte

Mã đánh gôn:

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

Ung dung:

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

Đầu ra:

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 để cạo byte đầu vào
CSᵠ

2

MATLAB, 96 88 87 86 79 byte

Đây là mã 79 byte, theo sau các đầu ra ví dụ (cụ thể là 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

Đây là 75 byte, có hành vi tương tự ngoại trừ n = 0 sẽ tạo ra một mảng trống theo hàm ý của câu hỏi (N by N mảng = 0 by 0 = mảng trống).

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

Điều này cũng hoạt động với Octave . Bạn có thể thử nó trực tuyến ở đây . Mã này đã được thêm dưới dạng một tệp có tên 'multspirus.m'. Vì vậy, tại dấu nhắc Octave, nhập multspiralvà nhấn enter. Sau đó, bạn nên nhập kích thước của bảng (ví dụ 4). Đầu ra sau đó sẽ được in.


Làm thế nào nó hoạt động?

Đầu tiên, việc này cần một số đầu vào theo yêu cầu (ví dụ: 6, 4, v.v.)

n=input('');

Sau đó, chúng tôi xử lý các trường hợp cho n=0n=1- chúng được xử lý đặc biệt vì chúng là hai trường hợp không tuân theo quy tắc tôi đang sử dụng để tạo các mảng - thực tế điều này có thể ngắn hơn 5 byte nếu không phải là n=0trường hợp tối nghĩa .

m=+(n>0);

Sau đó, đối với tất cả các giá trị của n>2, chúng tôi thực hiện một số vòng lặp cho đến khi ma trận được phát triển đến kích thước chính xác.

for i=2:n;

Thực tế chỉ có ba sự khác biệt đơn giản giữa nn+1cho tất cả n>=2. Đó là:

  1. Một cột mới được thêm vào ngoài cùng bên phải trong mảng chứa các số n(1:n). Điều này dễ dàng được tính toán với:

     a=i*(1:i);
    
  2. Bất kỳ yếu tố nào sẽ được thêm vào trong cột mới đó phải được xóa khỏi ma trận hiện có (được đặt thành 0) vì chúng sẽ luôn đến sau trong vòng xoắn ốc so với cột mới. Điều này được loại bỏ bằng cách sử dụng vòng lặp lồng nhau để đặt tất cả các phần tử trong ma trận hiện tại trong cột mới về 0.

    for j=a;
        m(m==j)=0;
    end;
    
  3. Có một hàng dưới cùng mới nhất mà mọi phần tử ngoại trừ phần tử nằm trong cột mới sẽ bằng không. Khi cột mới được thêm vào, do các chỉ số giới hạn được tạo ra có chủ ý được đệm tự động với 0. Một trong những tính năng mạnh mẽ của MATLAB là nó có thể phát triển các mảng mà không cần xử lý đặc biệt, vì vậy chúng tôi có thể thêm hàng và cột mới một cách đơn giản với:

    m(1:i,i)=a;
    

Cuối cùng, chúng ta có kết thúc vòng lặp for - một khi đã đạt tới, ma trận mchứa đầu ra của chúng ta. Khi bạn linh hoạt với định dạng đầu ra của mình, ma trận được hiển thị bằng cách đơn giản là có mmột dòng mới mà không có dấu chấm phẩy

end;
m

Ví dụ: nếu chúng tôi chạy chương trình, nhập số 10, chúng tôi sẽ nhận được kết quả sau:

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 byte

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

Ví dụ sử dụng: f 4-> [[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]].

Tôi vừa phát hiện ra Data.Listsmô-đun có các chức năng hay trong danh sách (như replace) và tái xuất Data.List, Data.List.SplitData.List.Extras.


1

Ruby, 67 63 61 byte

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

63 byte

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

67 byte

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

Sử dụng:

->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]]
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.