Đếm các hình vuông


18

Thử thách

Origami (gấp giấy) là một hình thức nghệ thuật sáng tạo. Theo tôi biết, chủ nhân của Origami thích giấy vuông. Hãy bắt đầu lại từ đầu - chuyển đổi một tờ giấy hình chữ nhật thành một hình vuông.

Vì vậy, giấy được chia thành hình vuông. Chúng tôi xóa hình vuông lớn nhất chia sẻ một cạnh ngắn hơn với hình dạng hiện tại, từng bước một (xem hình dưới đây). Và nếu phần còn lại sau một bước nhỏ hơn hoặc bằng 0.001 * (area of the original paper), thì tờ giấy không thể được chia thêm nữa. Có thể là không có gì còn lại cuối cùng.

Nhiệm vụ của bạn là tính toán có bao nhiêu hình vuông được thực hiện trong quá trình. Hình vuông ở bước cuối cùng làm cho giấy không thể phân chia được tính vào đầu ra.

Ví dụ (một tờ giấy có 1.350chiều rộng / chiều cao), đầu ra là 10:

ví dụ lát

Đầu vào và đầu ra

Đầu vào: tỷ lệ chiều rộng / chiều cao cho giấy hình chữ nhật, một số thập phân (hoặc số nguyên không có dấu chấm) từ 1.002đến 1.999với một bước tối thiểu là0.001 . Bạn cũng có thể sử dụng bất kỳ định dạng hợp lý khác mô tả tỷ lệ. Chỉ cần đề cập đến nó trong câu trả lời của bạn.

Đầu ra: số vuông, một số nguyên.

Ví dụ I / O

Một định dạng ánh xạ được sử dụng để giữ cho trang gọn gàng, trong khi mã của bạn không cần hỗ trợ đầu vào danh sách cũng không phải là chức năng ánh xạ.

1.002 => 251
1.003 => 223
1.004 => 189
1.005 => 161
1.006 => 140
1.007 => 124
1.008 => 111
1.009 => 100

Danh sách tất cả các câu trả lời

Cảm ơn @LuisMendo, đây là biểu đồ câu trả lời.

đồ thị

Nhận xét

  • Đây là một môn đánh gôn nên mã ngắn nhất sẽ thắng
  • Chú ý đến sơ hở tiêu chuẩn
  • Bạn có quyền tự do quyết định cách xử lý đầu vào và đầu ra nhưng họ phải tuân theo các hạn chế tiêu chuẩn.

Nhân tiện...

  • Nhận xét nếu bạn có bất cứ điều gì không rõ ràng về thử thách
  • Cá nhân tôi sẽ đề nghị câu trả lời của bạn chứa một lời giải thích nếu bạn đang sử dụng ngôn ngữ chơi gôn
  • Cảm ơn @GregMartin, hãy đọc câu trả lời của anh ấy để có lời giải thích toán học tốt cho thử thách.

Mã ví dụ

Đây là phiên bản không mã hóa của mã C ++:

#include <iostream>
#include <utility>

int f (double m)
{
    double n = 1, k = 0.001;
    int cnt = 0;
    k *= m;                       // the target minimum size
    while(m*n >= k)
    {
        m -= n;                   // extract a square
        if(n > m)
            std::swap(n, m);      // keep m > n
        ++ cnt;
    }
    return cnt;
}

int main()
{
    double p;
    std::cin >> p;
    std::cout << f(p);
    return 0;
}

Tất cả các tính toán liên quan trong mã ví dụ cần độ chính xác 6 chữ số thập phân, được trình bày trong float.


Hai số hình thành tỷ lệ có thể được sử dụng làm đầu vào?
Luis Mendo

@LuisMendo có, như mong muốn của bạn.
Keyu Gan

2
Thử thách gọn gàng!
flawr

5
Danh sách các câu trả lời tạo ra một biểu đồ đẹp
Luis Mendo

1
@KeyuGan Tất nhiên, đi tiếp! Hãy cho tôi biết nếu bạn cần một phiên bản với một số định dạng khác
Luis Mendo

Câu trả lời:


2

MATL , 19 byte

`SZ}y-htG/p1e-3>}x@

Đầu vào là một mảng với hai số xác định tỷ lệ ban đầu, chẳng hạn như [1, 1.009]. (Không cần thiết phải sắp xếp các số hoặc một trong số chúng là 1.)

Hãy thử trực tuyến!

Giải trình

`        % Do...while loop
  S      %   Sort array. Takes 1×2 array as input (implicit) the first time
  Z}     %   Split array into its 2 elements: first the minimum m, then the maximum M
  y      %   Duplicate m onto the top of the stack. The stack now contains m, M, m
  -      %   Subtract. The stack now contains m, M-m
  h      %   Concatenate into [m, M-m]. This is the remaining piece of paper
  t      %   Duplicate
  G/     %   Divide by input, element-wise
  p      %   Product of array. Gives ratio of current piece's area to initial area
  1e-3>  %   True if this ratio exceeds 1e-3. In that case the loop continues
}        % Finally (execute after last iteration, but still within the loop)
  x      %   Delete last piece of paper
  @      %   Push current loop counter. This is the result
         % End (implicit)
         % Display (implicit)

6

Haskell , 71 70 65 63 62 61 58 56 byte

Cảm ơn @xnor vì một số cải tiến khéo léo!

(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1
n!m=n#m$n*m

Hãy thử trực tuyến!


Nó nghĩ rằng m==ncuối cùng có thể là 1>0vì đó là khả năng duy nhất còn lại. Hoặc, có lẽ các trường hợp có thể được sắp xếp lại để cho phép một ràng buộc ở đây.
xnor

Trên thực tế, là trường hợp bình đẳng cần thiết? Nếu n>mđược mở rộng thành n>=mvà kiểm tra đầu tiên được viết e>m*n*1000, điều đó sẽ 1cho sự bình đẳng.
xnor

@xnor Ý kiến ​​hay, cảm ơn bạn!
flawr

1
Di chuyển xung quanh lính gác trong 56:(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1;n!m=n#m$n*m
xnor

Wow, sử dụng d<-n-mnhư otherwiselà thực sự gọn gàng !!!
flawr

4

JavaScript (ES6), 59 58 byte

f=(m,n=!(k=m/1e3,c=0))=>m*n<k?c:(c++,m-=n)<n?f(n,m):f(m,n)

Kiểm tra


4

Mathicala, không cạnh tranh (21 byte)

Câu trả lời này không cạnh tranh vì không trả lời được câu hỏi thực tế! Nhưng nó trả lời một biến thể của câu hỏi, và cung cấp một cái cớ để làm nổi bật một số toán học thú vị.

Tr@*ContinuedFraction

Hàm tượng trưng lấy một số hữu tỷ dương làm đầu vào (có tử số và mẫu số đại diện cho kích thước của giấy gốc) và trả về một số nguyên dương. Ví dụ, Tr@*ContinuedFraction[1350/1000]trả về 10. (ContinuedFraction hoạt động khác nhau trên các số có dấu phẩy động do các vấn đề chính xác, đó là lý do tại sao cần một số hữu tỷ làm đầu vào trong ngữ cảnh này.)

Một cách giải thích thú vị về quy trình hình học được mô tả trong bài toán (cắt hình vuông ra một hình chữ nhật lặp đi lặp lại) đó là việc thực hiện thuật toán Euclide để tìm các ước số chung lớn nhất! Xem xét ví dụ trong chính câu hỏi, với tỷ lệ1.35, có thể được mô hình hóa bằng cách có một mảnh giấy có kích thước (1350,1000). Mỗi khi một hình vuông bị cắt đi, số nhỏ hơn sẽ bị trừ khỏi số lớn hơn; do đó, các hình chữ nhật thu được trong ví dụ này có các kích thước (350,1000), sau đó (350,650), sau đó (350,300), sau đó (50,300), sau đó (50,250) và (50,200) và (50,150) và (50,100) và (50, 50), và cũng (50,0) một khi chúng ta lấy đi hình vuông cuối cùng từ chính nó. Đây chính xác là cách thuật toán Euclide vận hành (modulo sự khác biệt giữa phép chia và phép trừ lặp lại) và thực sự chúng ta thấy rằng 50 thực sự là GCD của 1350 và 1000.

Thông thường trong thuật toán Euclide, người ta theo dõi các kích thước trung gian này và loại bỏ số phép trừ; tuy nhiên, người ta có thể luân phiên ghi lại số lần chúng ta trừ đi một số từ số kia trước khi chênh lệch trở nên quá nhỏ và chúng ta phải chuyển đổi những gì chúng ta đang trừ. Phương pháp ghi đó chính xác là phần tiếp tục của một số hữu tỷ. (Tiếp tục các phân số của số vô tỷ, không bao giờ chấm dứt, cũng cực kỳ hay, nhưng không liên quan ở đây.) Ví dụ, trong ví dụ 1350/1000, chúng tôi đã trừ 1000 1lần, sau đó 350 2lần, sau đó 300 1lần, sau đó 50 6lần; do đó, phần tiếp tục của 1350/1000 là {1,2,1,6}. Về mặt toán học, chúng tôi đã viết lại 1350/1000 thành 1+ 1 / ( )), mà bạn có thể xác minh.2 + 1 / ( 1+ 1 /6

Vì vậy, đối với vấn đề này, nếu bạn không dừng lại khi các ô vuông nhỏ hơn một ngưỡng nhất định, mà chỉ cần đếm tất cả các ô vuông chính xác trước khi nó dừng lại, thì tổng số ô vuông bằng tổng số phép trừ, nghĩa là tổng của tất cả các số nguyên trong phân số liên tục, và đó chính xác là thành phần của các hàm Tr@*ContinuedFractiontính toán! (Đối với ví dụ 1.35 đã cho, câu trả lời mà OP mong muốn, bởi vì hình vuông cuối cùng đủ lớn để tất cả các hình vuông được tính. Nhưng Tr@*ContinuedFraction[1001/1000], ví dụ, sản lượng 1001, vì nó tính một hình vuông lớn và tất cả 1000 hình vuông 1x1000 nhỏ .)


1
Mặc dù điều này thực sự thú vị, nhãn không cạnh tranh được dành riêng cho các ngôn ngữ mới hơn thách thức . Độc lập về điều đó, tất cả các câu trả lời cần phải giải quyết thách thức. Do đó, câu trả lời này thực sự nên được xóa. Bạn có thể xây dựng lại từ danh sách phân số tiếp tục để cắt nó đi để điều này có thể trở thành một giải pháp thú vị không kém nhưng hợp lệ không?
Martin Ender

1
Tôi đã bị ngứa tinh thần khi viết câu trả lời này, nhưng tôi đồng ý rằng đây là câu trả lời đáng xóa theo tiêu chuẩn cộng đồng. (Cảm ơn bạn đã phản hồi nhẹ nhàng nhưng chính xác!) Nếu TPTB cảm thấy muốn trì hoãn việc xóa nó trong 24 giờ, tôi có thể phàn nàn cách tiếp cận để đưa ra câu trả lời đúng ... nếu không, hãy xóa đi và không có cảm giác khó khăn.
Greg Martin

3

Toán học, 64 53 byte

({t=1,#}//.{a_,b_}/;1000a*b>#:>Sort@{++t;a,b-a};t-1)&

Một giải pháp bắt buộc (kiểu C) có cùng độ dài:

(For[t=a=1;b=#,1000a*b>#,If[a>b,a-=b,b-=a];++t];t-1)&

2

C (GCC / Clang), 61 59 byte

c,k;f(m,n){for(k=m*n;m*n/k;m>n?(m-=n):(n-=m))++c;return c;}

Đầu vào là hai số nguyên (chiều rộng và chiều cao) không có dấu chấm, chẳng hạn như f(1999,1000).

Tôi hy vọng ai đó có thể lưu một byte đẩy C vào câu lạc bộ 58 byte. ;)


Đề nghị loại bỏ các dấu ngoặc đơn xung quanhm-=n
trần nhà

1

C, 59 byte

s,a,n=1e3;C(m){for(a=m;m*n>a;s++)m>n?m-=n:(n-=m);return s;}

Dùng thử trực tuyến

Đầu vào là một số nguyên là tỷ lệ chiều rộng / chiều cao tính bằng phần nghìn (ví dụ: 1002 cho 1.002: 1).

Phiên bản ung dung

int C(int m)
{
    int n = 1000;
    int a = m;
    int s = 0;

    while (m * n > a)
    {
        if (m > n)
            m -= n;
        else
            n -= m;

        s++;
    }

    return s;
}
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.