Tính tất cả các hình vuông lên đến x chỉ bằng phép cộng và phép trừ


11

Mục tiêu là tính toán tất cả các hình vuông cho đến xkhi cộng và trừ.

Quy tắc:

  1. Mã phải là một hàm lấy tổng số ô vuông để tạo và trả về một mảng chứa tất cả các ô vuông đó.
  2. Bạn không thể sử dụng các chuỗi, cấu trúc, nhân, chia hoặc các hàm dựng sẵn để tính toán các hình vuông.
  3. Bạn chỉ có thể sử dụng mảng, số nguyên (số nguyên), cộng, trừ. Không cho phép các nhà khai thác khác!

Đây là một câu hỏi về , vì vậy mã ngắn nhất tính bằng byte sẽ thắng!


Đây thực chất là thuật toán được tối ưu hóa nhất để tăng bình phương - hoặc, ít nhất, sẽ nhận được khá nhiều câu trả lời giống hệt nhau.
Peter Taylor

2
@PeterTaylor Không, nó không giống nhau, vì đó là thuật toán được tối ưu hóa nhất để tăng bình phương, nhưng câu hỏi của tôi chỉ yêu cầu cộng và trừ.
Bàn chải đánh răng

Đó là điều tương tự. Là nhân chứng: câu trả lời hiện tại cho câu hỏi này thực hiện giống hệt như phần lớn câu trả lời cho câu hỏi trước đó.
Peter Taylor

@PeterTaylor Tôi có thể bị thiên vị, nhưng tôi thực sự không nghĩ nó giống nhau.
Bàn chải đánh răng

3
Câu hỏi này có thể đã có câu trả lời ở nơi khác, nhưng điều đó không làm cho câu hỏi trở thành một bản sao của câu hỏi khác.
Blacklight Shining

Câu trả lời:



6

C, 55 52 byte

int s(int n,int*r){for(int i=0,j=-1;n--;*r++=i+=j+=2);}

chỉ đơn giản là tổng các số lẻ

  • n: số ô vuông để tính
  • r: mảng đầu ra để lưu trữ kết quả
  • j: lấy các giá trị liên tiếp 1, 3, 5, 7, ...
  • i: được tăng lên theo jmỗi lần lặp

Biên tập

Có thể lưu 4 ký tự bằng cách sử dụng khai báo int ẩn (> C99), nhưng chi phí này là 1 char vì bộ forkhởi tạo không thể chứa khai báo trong> C99. Sau đó, mã trở thành

s(int n,int*r){int i=0,j=-1;for(;n--;*r++=i+=j+=2);}

Sử dụng

void main() {
    int r[20];
    s(20, r);
    for (int i = 0; i < 20 ; ++i) printf("%d\n", r[i]);
}  

Đầu ra

1
4
9
16
25
36
49
(...)
361
400

1
logic đó là tuyệt vời! bạn xứng đáng +1
Mukul Kumar

5

GolfScript, 17 ký tự

{[,{.+(1$+}*]}:F;

Cách sử dụng (xem thêm ví dụ trực tuyến ):

10 F     # => [0 1 4 9 16 25 36 49 64 81]

Lưu ý: * là một vòng lặp và không phải là toán tử nhân.


ĐỒNG Ý; làm thế nào nó hoạt động?
Bàn chải đánh răng

@toothbrush ,lấy đầu vào và chuyển đổi nó thành mảng [0 1 ... n-1]. Sau đó *tiêm khối mã đã cho vào mảng. Khối này trước tiên nhân đôi mục hiện tại ( .+) trừ đi một ( () và sau đó thêm kết quả trước đó 1$+(nói cách khác, thêm 2j-1vào số vuông trước đó). []kèm theo mọi thứ để trả về một mảng mới.
Howard

Tuyệt quá! Tôi không biết GolfScript, vì vậy tôi tự hỏi làm thế nào nó hoạt động.
Bàn chải đánh răng

5

Batch Windows, 115 byte

setlocal enabledelayedexpansion&for /l %%i in (1 1 %1)do (set a=&for /l %%j in (1 1 %%i)do set /a a+=%%i
echo.!a!)

Điều này nên được đặt trong một tệp bó thay vì được chạy từ cmd và nó xuất danh sách ra bàn điều khiển. Nó lấy số lượng hình vuông để tạo từ đối số dòng lệnh đầu tiên. Đối với hầu hết các phần nó sử dụng &thay vì dòng mới, tuy nhiên vẫn cần một và nó được tính là hai byte.

Nó cần mở rộng biến bị trì hoãn kích hoạt, điều này có thể được thực hiện với cmd /v:on. Giả sử không phải vậy, cần có thêm một phần bổ sung setlocal enabledelayedexpansion&khi bắt đầu (không có nó thì tập lệnh là 83 byte).


4

Haskell - 30

f n=scanl1(\x y->x+y+y-1)[1..n]

Điều này sử dụng thực tế là (n+1)^2=n^2+2n+1


4

Perl, 27 byte

sub{map{$a+=$_+$_-1}1..pop}

Môn Toán:

môn Toán

Tập lệnh gọi hàm để in 10 ô vuông:

#!/usr/bin/env perl
$square = sub{map{$a+=$_+$_-1}1..pop};
use Data::Dumper;
@result = &$square(10);
print Dumper \@result;

Kết quả:

$VAR1 = [
          1,
          4,
          9,
          16,
          25,
          36,
          49,
          64,
          81,
          100
        ];

Chỉnh sửa:


Tôi thấy không có lý do tại sao bạn cần phải đặt tên phụ của bạn. IOW "sub {map {$ a + = $ _ + $ _- 1} 1..shift}" có vẻ hợp pháp với tôi và giúp bạn tiết kiệm được hai ký tự.
skibrianski

@skibrianski: Một chức năng ẩn danh cũng là một chức năng. Nhược điểm là việc gọi hàm có phần cồng kềnh hơn một chút.
Heiko Oberdiek

Phải, nhưng đó là trên người gọi. Có các mục trong các ngôn ngữ khác xác định chương trình phụ ẩn danh, vì vậy tôi nghĩ rằng bạn an toàn =)
skibrianski

Và bạn có thể lưu 2 ký tự khác bằng cách sử dụng pop () thay vì shift () vì chỉ có một đối số.
skibrianski

@skibrianski: Phải, cảm ơn.
Heiko Oberdiek

4

JavaScript - 32 ký tự

for(a=[k=i=0];i<x;)a[i]=k+=i+++i

Giả sử một biến xtồn tại và tạo ra một mảng acác ô vuông cho các giá trị 1..x.

ECMAScript 6 - 27 ký tự

b=[f=i=>b[i]=i&&i+--i+f(i)]

Gọi f(x)sẽ điền vào các mảng bvới các hình vuông cho các giá trị 0..x.


Tôi phải hỏi ... i+++icuối cùng ...?
WallyWest

2
k+=i+++ilà tương k += i + (++i)tự như k+=i+i+1saui=i+1
MT0

Ôi thật là thiên tài ... Tôi phải thực hiện điều đó trong codegolf tiếp theo của mình nếu cần! :)
WallyWest

Bạn có thể lưu một ký tự bằng cách di chuyển khai báo hàm vào bên trong mảng (ví dụ b=[f=i=>b[i]=i&&i+--i+f(i)]).
Bàn chải đánh răng

Cảm ơn - đã lưu một ký tự trên câu trả lời hàng đầu bằng cách di chuyển mọi thứ để loại bỏ dấu chấm phẩy.
MT0

4

Julia - 33

Bất kỳ số vuông nào cũng có thể được viết bằng tổng các số lẻ:

julia> f(x,s=0)=[s+=i for i=1:2:(x+x-1)];f(5)
5-element Array{Int64,1}:
  1
  4
  9
 16
 25

Xin chào, và chào mừng bạn đến với CG.se! Đẹp, trả lời ngắn gọn. Chưa bao giờ nghe nói về Julia, nhưng nó có vẻ hấp dẫn.
Jonathan Van Matre

Không phải là "gấp đôi" một phép nhân trong Julia sao? Bạn có thể nói x + x thay vào đó, sẽ tốn của bạn chỉ một byte.
Glenn Randers-Pehrson

Bạn đã đúng (không thông báo), chỉnh sửa.
ĐCSTQ

Tôi chưa quen (chưa) với julia, nhưng đã tìm nó trong hướng dẫn trực tuyến tại docs.julialang.org/en/release-0.2 và tìm thấy "Hệ số chữ số: Để làm cho các công thức và biểu thức số phổ biến rõ ràng hơn, Julia cho phép các biến ngay lập tức đi trước một chữ số, hàm ý nhân. " Vì vậy, yeah, 2x là một phép nhân.
Glenn Randers-Pehrson

2

C ++ 99 81 78 80 78

int* f(int x){int a[x],i=1;a[0]=1;while(i<x)a[i++]=a[--i]+(++i)+i+1;return a;}  

lần thử đầu tiên của tôi trong môn đánh gôn

mã này dựa trên
a = 2 xn - 1
trong đó n là số hạng hạn và a là số hạng thứ n trong chuỗi sau
1, 3, 5, 9, 11, 13, .....
tổng của 2 số hạng đầu tiên = 2 bình phương

tổng của 3 số hạng đầu tiên = 3 bình phương
và cứ thế ...


2
Tôi nghĩ bạn có thể loại bỏ các dấu ngoặc nhọn {}sau forvòng lặp, vì chỉ có một câu lệnh. Điều này có thể làm giảm số lượng char của bạn xuống 2
user12205

1
Nếu bạn khai báo các mảng có kích thước không cố định trong một số chức năng khác ngoài hàm chính () thì có thể chấp nhận được
Mukul Kumar

1
Mã này có hành vi không xác định.
Kerrek SB

1
và trả về con trỏ tới dữ liệu trên stack bị hủy trong quá trình trả về.
VX

1
@MukulKumar addition, subtraction, tôi chỉ sử dụng những thứ đó
mniip

2

Hội DCPU-16 (90 byte)

Tôi đã viết điều này trong lắp ráp cho một bộ xử lý hư cấu, bởi vì tại sao không?

:l
ADD I,1
SET B,0
SET J,0
:m
ADD J,1
ADD B,I
IFL J,I
SET PC,m
SET PUSH,B
IFL I,X
SET PC,l

Số lượng dự kiến ​​sẽ nằm trong thanh ghi X và các thanh ghi khác dự kiến ​​là 0. Kết quả được đẩy lên ngăn xếp, nó sẽ bị phá vỡ khi đạt tới 65535 do kiến ​​trúc 16 bit. Bạn có thể muốn thêm một SUB PC, 1vào cuối để kiểm tra nó. Được biên dịch, chương trình nên có 20 byte (10 từ).


2

Haskell

f x=take x [iterate (+y) 0 !! y | y<- [0..]]

Điều này về cơ bản phát minh ra phép nhân, sử dụng chính nó và ánh xạ nó trên tất cả các số. f 10= [0,1,4,9,16,25,36,49,64,81]. Ngoài ra f 91= [0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400,441,484,529,576,625,676,729,784,841,900,961,1024,1089,1156,1225,1296,1369,1444,1521,1600,1681,1764,1849,1936,2025,2116,2209,2304,2401,2500,2601,2704,2809,2916,3025,3136,3249,3364,3481,3600,3721,3844,3969,4096,4225,4356,4489,4624,4761,4900,5041,5184,5329,5476,5625,5776,5929,6084,6241,6400,6561,6724,6889,7056,7225,7396,7569,7744,7921,8100].


Bạn có thể mở rộng bản demo lên lớn hơn 10 không?
Glenn Randers-Pehrson

2

Haskell, 34/23

n#m=m+n:(n+2)#(m+n)
f n=take n$1#0

hoặc, nếu nhập khẩu được:

f n=scanl1(+)[1,3..n+n]

Đầu ra:

λ> f 8
[1,4,9,16,25,36,49,64]

1

Javascript 47

function f(n,a){return a[n]=n?f(n-1,a)+n+n-1:0}

r=[];f(12,r);console.log(r) trả về:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144]


Tuyệt quá! Trong EcmaScript 6 : f=(n,a)=>a[n]=n?f(n-1,a)+n+n-1:0.
Bàn chải đánh răng

1
Tôi thực sự không thể chờ ECMAScript 6 thực sự đi vào sử dụng chính. Đó sẽ là cái cớ hoàn hảo để học nó.
Isiah Meadows

1
Phần Chức năng Mũi tên của đặc tả ECMAScript 6 đã có trong FireFox kể từ phiên bản 22.
MT0

1

Smalltalk, 52

f:=[:n||s|(s:=1)to:n collect:[:i|x:=s.s:=s+i+i+1.x]]

Trả về một mảng mới (tức là không điền hoặc thêm vào một mảng hiện có).

gọi:

giá trị f: 10

-> # (1 4 9 16 25 36 49 64 81 100)


1

trăn - 39

a=0
for i in range(5):a+=i+i+1;print(a)

Thay thế 5bằng bất kỳ giá trị. Bất kỳ đề xuất?


1

Bash - 92 85 62 61 59 57

declare -i k=1;for((i=0;i++<$1;k+=i+i+1));do echo $k;done

Kết quả:

$ ./squares.sh 10
1
4
9
16
25
36
49
64
81
100

Chỉnh sửa: Tôi đã thay thế vòng lặp bên trong bằng thuật toán từ giải pháp Haskell của @ mniip.


1

Phương pháp tương tự như trên, trong APL và J:

APL: F←{+\1+V+V←¯1+⍳⍵}(17 ký tự) hoạt động với hầu hết các biến thể APL (thử tại đây )

và thậm chí ít hơn (chỉ 14 ký tự) với NGN APL: F←{+\1+V+V←⍳⍵}(xem tại đây )

J: f=:+/\@(>:@+:@:i.)(18 ký tự)

chỉnh sửa: giải pháp tốt hơn trong APL: F←{+\¯1+V+V←⍳⍵}(15 ký tự)


1

C # (82)

int[] s(int n){int i,p=0;var r=new int[n];while(i<n){p+=i+i+1;r[i++]=p;}return r;}

1

C # - 93

int[]s(int l){int[]w=new int[l];while(l>=0){int i=0;while(i<l){w[l-1]+=l;i++;}l--;}return w;}

Khi được gọi từ một phương thức khác của cùng một lớp, sẽ trả về mảng - [1,4,9,16,25,36...], cho đến lphần tử thứ.


bạn đã thử loại bỏ khoảng cách giữa int[]sq? Tôi không biết C #, nhưng tôi nghĩ nó sẽ hoạt động.
dùng12205

Không, điều đó sẽ không làm việc. Int đầu tiên [] là kiểu trả về của phương thức "sq". Tôi có thể giảm tên phương thức thành có thể chỉ là "s" :)
Rajesh

Tôi có nghĩa là sử dụng int[]sqthay vì int[] sqint[]resthay vì int[] res. Điều này giúp bạn lưu hai ký tự và tôi không gặp phải lỗi biên dịch nào với điều đó. Ngoài ra, bạn nên sử dụng định danh ký tự đơn cho sqresnhư bạn đề xuất.
dùng12205

có vẻ như có gì đó không đúng với câu trả lời của bạn
user12205

Mã thụt lề với 4 khoảng trắng để đặt nó trong một khối mã với phông chữ đơn cách.
luser droog

1

Fortran II | IV | 66 | 77, 134 122 109 105

  SUBROUTINES(N,M)
  INTEGERM(N)
  K=0
  DO1I=1,N
  K=K+I+I-1
1 M(I)=K
  END

Chỉnh sửa: loại bỏ vòng lặp bên trong và sử dụng thuật toán Haskell của @ mniip thay thế.

Chỉnh sửa: Xác minh rằng chương trình con và trình điều khiển là hợp lệ Fortran II và IV

Người lái xe:

  INTEGER M(100)
  READ(5,3)N
  IF(N)5,5,1
1 IF(N-100)2,2,5
2 CALLS(N,M)
  WRITE(6,4)(M(I),I=1,N)
3 FORMAT(I3)
4 FORMAT(10I6)
  STOP  
5 STOP1
  END

Kết quả:

$ echo 20 | ./a.out
   1     4     9    16    25    36    49    64    81   100
 121   144   169   196   225   256   289   324   361   400

@mniip, cảm ơn, tôi đã thay thế vòng lặp bên trong của tôi bằng mã của bạn.
Glenn Randers-Pehrson

1

Con trăn - 51

Ở đây tôi đang xác định một chức năng theo yêu cầu của các quy tắc.

Sử dụng sumsố lẻ:

f=lambda n:[sum(range(1,i+i+3,2))for i in range(n)]

Điều này chỉ sử dụng sum(một nội dung thực hiện bổ sung) và range(một nội dung tạo ra các mảng sử dụng phép cộng). Nếu bạn phản đối sum, chúng tôi có thể làm điều này với reduce:

def g(n):v=[];reduce(lambda x,y:v.append(x) or x+y,range(1,i+i+3,2));return v

1

PHP, 92 byte

Tất nhiên, điều này cần phải bật tùy chọn "thẻ ngắn" (để tắt 3 byte khi bắt đầu).

<? $x=100;$a=1;$r=0;while($r<=$x){if($r){echo"$r ";}for($i=0,$r=0;$i<$a;$i++){$r+=$a;}$a++;}

Đầu ra:

1 4 9 16 25 36 49 64 81 100 

1

Forth - 48 byte

: f 1+ 0 do i 0 i 0 do over + loop . drop loop ;

Sử dụng:

7 f

Đầu ra:

0 1 4 9 16 25 36 49
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.