In một bộ Cantor


19

Các thách thức

Xây dựng một N-san Cantor Set .

Bộ ternary Cantor được tạo bằng cách xóa liên tục phần ba mở giữa của một tập hợp các phân đoạn dòng.

Chương trình nhận một tham số N(số nguyên) và sau đó in (trong bảng điều khiển hoặc cách tương tự) một Tập hợp các cấp độ N. Bản in chỉ có thể chứa các _ký tự dấu gạch dưới ( ) và dấu cách. Tham số có thể là dương hoặc âm và dấu hiệu cho biết hướng xây dựng Bộ Cantor: Nếu N > 0Bộ Cantor được xây dựng xuống và nếu N < 0Bộ Cantor được xây dựng lên. Nếu N = 0sau đó chương trình in một dòng duy nhất ( _).

Ví dụ:

N = 2

_________
___   ___
_ _   _ _

N = -2

_ _   _ _
___   ___
_________

N = 3

___________________________
_________         _________
___   ___         ___   ___
_ _   _ _         _ _   _ _

N = -3

_ _   _ _         _ _   _ _
___   ___         ___   ___
_________         _________
___________________________

Tiêu chí chiến thắng

Vì nó là một thử thách golf mã, mã ngắn nhất sẽ thắng.

Đã chỉnh sửa: Sửa đổi 0 đầu vào theo đề xuất của ugoren.


Tại sao không in gì khi N = 0? Điều này làm cho 0 trở thành một trường hợp đặc biệt và làm cho việc sử dụng đệ quy trở nên khó khăn hơn. Xử lý chung sẽ là in một _(nhưng in xuống dưới khi nhận -0).
ugoren

Đúng. Tôi đã sửa đổi các thông số kỹ thuật rồi.
Averroes

Câu trả lời:


10

GolfScript, 49 42 40 ký tự

~.abs.3\?'_'*\{.3%..,' '*\++}*](0>2*(%n*

Cảm ơn hammar cho 42-> 40.

Nỗ lực tốt nhất của tôi theo cách tiếp cận lý thuyết số nhiều hơn đáng buồn là lâu hơn nhiều:

~.abs:^3\?,{3^)?+3base(;1+1?.'_'*^@-)' '*+}%zip\0>2*(%n*

hoặc là

~.abs 3\?:^,{6^*+3base.1+1?.('_'*@,@-' '*+}%zip\0>2*(%n*

và tôi nghi ngờ rằng độ dài basezipsẽ khiến nó không thể bắt kịp.


~.abs.@/\.3\?'_'*\{.3%..,' '*\++}*](%n*là 39 ký tự, nhưng sự cố về đầu vào 0. :-(
Ilmari Karonen

@IlmariKaronen, vâng, chia cho số 0 là một nỗi đau cho việc thực hiện C tôi cũng đã viết, bởi vì điều đó có nghĩa là bạn không thể làm gì n/abs(n)để có được signum(n).
Peter Taylor

6

Python, 116 113 104 103 ký tự

n=input()
d=n>0 or-1
for i in range(n*d+1)[::d]:
 s='_'*3**i
 while i<n*d:s+=len(s)*' '+s;i+=1
 print s

Thuật toán cũ đứng đầu với 113 ký tự

r=input()
u='_'
l=[u]
for _ in abs(r)*u:o=len(l[0]);l=[s+o*' '+s for s in l]+[u*o*3]
print'\n'.join(l[::r>0 or-1])

5

Hồng ngọc (97)

Dựa trên phiên bản trăn của Steven Rumbalski:

n,r=$*[0].to_i,[?_]
n.abs.times{z=r[0].size;r=r.map{|s|s+' '*z+s}+[?_*z*3]}
puts n<0?r:r.reverse

Những lần thử trước, cả hai cùng chiều dài (112)

Xây dựng các dòng từ các bộ phận:

c=->x,n{n<1??_*x :(z=c[s=x/3,n-1])+' '*s+z}
r=(0..m=(n=$*[0].to_i).abs).map{|i|c[3**m,i]}
puts n<0?r.reverse: r

Bắt đầu với một dòng, tạo lỗ hổng trong nó:

r=[?_*3**a=(n=$*[0].to_i).abs]
a.times{|c|r<<r[-1].gsub((x=?_*o=3**(a-c-1))*3,x+' '*o+x)}
puts n<0?r.reverse: r

3

Perl, 93 ký tự

@x=($t=$x=_ x 3**($a=abs($n=<>)),map$x.=$"x($x=~s/(.)../$1/g).$x,1..$a);say for$n<0?sort@x:@x

Tôi nghĩ tôi sẽ thử xem giải pháp GolfScript của Peter Taylor sẽ chuyển đến Perl tốt như thế nào . Các tính năng đáng chú ý bao gồm việc sử dụng sortthay vì reverseđể lưu ba ký tự, sử dụng thực tế là một không gian sắp xếp trước đó _.


2

Lisp thông thường, 217 210 ký tự

(defun m(x)(flet((c(n v)(if(= n 0)`((,v))(cons(substitute v nil(make-list(expt 3 n)))(mapcar #'append(c(1- n)v)(c(1- n)" ")(c(1- n)v))))))(format t "~{~{~a~}~%~}"(let((r(c(abs x)'_)))(if(< x 1)(reverse r)r)))))

Mở rộng:

(defun m(x)
  (flet((c(n v)
    (if(= n 0)
       `((,v))
       (cons(substitute v nil(make-list(expt 3 n)))
            (mapcar #'append
                    (c(1- n)v)
                    (c(1- n)" ")
                    (c(1- n)v))))))
   (format t "~{~{~a~}~%~}"(let((r(c(abs x)'_)))(if(< x 1)(reverse r)r)))))

Tôi hình dung nếu mã Lisp quản lý để đánh bại bất kỳ số đếm ban đầu nào cho ngôn ngữ khác (C, 219) Tôi đang làm tốt :)


2

C ( 163 161 ký tự)

i,l,N;f(n,m,s){if(n){s=--n<l?m:s;f(n,m,s);f(n,s,s);f(n,m,s);}else
putchar(m);}main(n,v)int**v;{for(i=N=abs(n=atoi(1[v]));i+1;i--)l=n<N?N-i:i,f(N,95,32),f(0,10);}

Mượn một vài mánh khóe từ câu trả lời của ugoren , nhưng logic cốt lõi thì hoàn toàn khác. Tôi không thể theo vòng lặp của anh ấy, vì vậy có thể lai và tiết kiệm thêm một vài thứ nữa.


2

C, 219 193 179 143 136 131 ký tự

Thực hiện theo các ý tưởng khác của Petyer Taylor, cộng với sự cải tiến của riêng tôi, đã tiết kiệm thêm 6 ý tưởng.
Tích hợp một số mẹo từ @PeterTaylor, cộng với sao chép chức năng chính của anh ấy, với những thay đổi nhỏ, giúp tiết kiệm một ký tự (sao chép công bằng? Vì cả hai chúng tôi sẽ không giành được cái này, tôi đoán nó không quá tệ).
Tôi đã nghĩ đến một sự cải thiện đáng kể trong cách thức đệ quy của tôi hoạt động, và sau khi thấy câu trả lời của Peter Taylor, tôi đã thực hiện nó để lấy lại vị trí dẫn đầu. Khi đọc câu trả lời của anh ấy một lần nữa, tôi thấy rằng tôi đã làm gần như chính xác những gì anh ấy đã làm. Vì vậy, điều này có vẻ như sự lai tạo mà ông đề xuất.
Cũng đơn giản hóa các vòng lặp trong main, giữ nguyên chiều dài.
Và lấy mẹo của Peter để in dòng mới, thay vì puts("")- lưu một ký tự.

Xóa intkhỏi khai báo biến - một cảnh báo, nhưng lưu 4 ký tự.
Thuật toán mới không tính toán trước 3 ^ x, nhưng sử dụng một vòng lặp duy nhất để in 3 ^ x ký tự.
Có thể lưu thêm một lần nữa bằng cách xác định int*v, nhưng sau đó 64 bit sẽ không hoạt động.
Số ký tự không bao gồm khoảng trắng (có thể được loại bỏ).

o,i,n;
p(c) {
    n-- ?
        p(c),p(o>n?c:32),p(c)
    :
        putchar(c);
    n++;
}
main(c,v)int**v; {
    for(n=abs(c=atoi(v[1]));i<=n;i++)o=c+n?n-i:i,p(95),puts("");
}

Thuật toán cũ hơn, ký tự 219:

p(l,o,i,m,c,j) {
    for(;i<(m=l);i++)
        for(j=0,c=95;m/o||!putchar(c);j++)
            i/m%3-1||(c=32),m/=3;
    puts("");
}
main(c,v,n,i,l,o)int**v;{
    (n=atoi(v[1]))<0?n=-n:(c=0);
    for(i=n,l=1;i;i--)l*=3;
    o=c?1:l;
    for (;i<=n;i++)p(l,o,0),c?o*=3:(o/=3);
}

@PeterTaylor, tôi không thể xóa itham số, vì sử dụng toàn cầu sẽ can thiệp vào main. l--sẽ can thiệp o>=lvà tôi sẽ phải thay thế nó >(vậy tại sao tôi lại viết nó như thể đó là một điều xấu?) Tôi cũng có thể sao chép bạn main, đơn giản và ngắn hơn của tôi.
ugoren

@PeterTaylor, bạn đã đúng i- Tôi đã bỏ lỡ thực tế là tôi thực sự không còn sử dụng nó nữa (tôi nghĩ bạn có nghĩa là tôi không vượt qua nó).
ugoren

Nhân tiện, tôi không phiền bạn đảm nhận chức năng chính của tôi. Nguyên tắc nhỏ của tôi là sao chép giải pháp của người khác để thay đổi một nhân vật là quá tích cực, sao chép giải pháp của người khác để viết lại một nửa của nó là hoàn toàn công bằng và có một khu vực màu xám ở giữa. Có lẽ chúng ta nên cố gắng đồng ý một số tiêu chuẩn cộng đồng về meta.
Peter Taylor

@PeterTaylor, tôi nghĩ rằng chúng tôi đã đạt đến một loại bế tắc. pBây giờ tôi có vẻ khá tối ưu và bạn mainthì tốt hơn (tôi không chắc nó tối ưu, nhưng không thể cải thiện hơn nữa). Vì vậy, ngoại trừ một cấu trúc chương trình khéo léo mới, cách duy nhất để đi là một trong hai chúng tôi sao chép mã của người khác.
ugoren

BTW Bạn đang đếm nhân vật của mình như thế nào? Bởi vì tôi tạo ra phiên bản mới nhất 138 ký tự của bạn chứ không phải 136.
Peter Taylor

2

J, 44 39 38 37 byte

' _'{~0&>_&(]|.)(,:1)1&(,],.0&*,.])~|

Sử dụng phép lặp để xây dựng bộ tiếp theo bắt đầu bằng 1 (đại diện _ ) ban đầu.

Sử dụng

   f =: ' _'{~0&>_&(]|.)(,:1)1&(,],.0&*,.])~|
   f 0
_
   f 1
___
_ _
   f _1
_ _
___
   f 2
_________
___   ___
_ _   _ _
   f _2
_ _   _ _
___   ___
_________
   f 3
___________________________
_________         _________
___   ___         ___   ___
_ _   _ _         _ _   _ _
   f _3
_ _   _ _         _ _   _ _
___   ___         ___   ___
_________         _________
___________________________

Giải trình

' _'{~0&>_&(]|.)(,:1)1&(,],.0&*,.])~|  Input: integer n
                                    |  Absolute value of n
                (,:1)                  The array [1]
                     1&(          )~   Repeat abs(n) times starting with x = [1]
                                 ]       Identity function, gets x
                            0&*          Multiply x by 0
                               ,.        Join the rows together
                         ]               Identity function, gets x
                          ,.             Join the rows together
                     1  ,                Prepend a row of 1's and return
      0&>                              Test if n is negative, 1 if true else 0
         _&(   )                       If n is negative
             |.                          Reverse the previous result
            ]                            Return that
                                       Else pass the previous result unmodified
' _'                                   The string ' _'
    {~                                 Select from the string using the result
                                       as indices and return

Tốt đẹp! Cá nhân tôi đã không thử, nhưng tôi thích sử dụng chương trình nghị sự @.- kết hợp với nó $:, có thể được sử dụng ở đây không? Ví dụ, một cái gì đó như (zero case)`(positive case)`(negative case)@.*, hoặc thậm chí có thể ":@_:`(positive case)`(|."1@$:)@.*.
Conor O'Brien

Tôi đã không thử một giải pháp đệ quy, nhưng tôi có thể thử nó.
dặm

2

R , 141 139 137 byte

m=abs(n<-scan());write("if"(n<m,rev,c)(c(" ","_")[Reduce(`%x%`,rep(list(matrix(c(1,1,1,1,0,1),3)),m),t(1))[,1+2^m-2^(m:0)]+1]),1,3^m,,"")

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

-15 byte cũng nhờ sử dụng '('chức năng nhận dạng của Giuseppe ; writethay vì catin đầu ra; sử dụng thông minh%x% .

-2 byte nhờ Kirill L. bằng cách sử dụng cthay vì '('làm chức năng nhận dạng.


một sản phẩm Kronecker có thể làm việc ở đây? %x%? Có thể có một số vấn đề với việc lấy các hàng xen kẽ có lẽ ...
Giuseppe

@Giuseppe Tôi đã thử, xây dựng dựa trên câu trả lời "Tạo một H H của tôi từ nhỏ hơn của H H S" ... Tôi sẽ thử lại lần nữa.
JayCe

Ah, vậy chính bạn là người đã ủng hộ điều đó. đó là lý do duy nhất tôi nghĩ đến kronquá! Tôi tưởng tượng điều này sẽ có thể đi xuống như 125 byte nếu chúng ta có thể tìm ra cách tiếp cận phù hợp.
Giuseppe

bạn có thể sử dụng `(`làm chức năng nhận dạng để bạn có thể sử dụng writetrực tiếp thay vì catvà một forvòng lặp. 141 byte
Giuseppe

@Giuseppe Tôi không có ý tưởng (nào có thể được sử dụng theo cách này hoặc if có thể được sử dụng để chọn từ hai chức năng. Và tôi sẽ bắt đầu sử dụng write ... tiết kiệm rất nhiều "\ n".
JayCe

1

Con trăn, 177 164 ký tự

N=input()
n=abs(N)
c=lambda x:0if x<1 else x%3==1or c(x/3)
r=["".join([["_"," "][c(x/3**i)]for x in range(3**n)])for i in range(n+1)]
print"\n".join(r[::N>0 or-1])

Vì bạn đang sử dụng Python 2, bạn không cần phải đưa ra kết quả inputint. Hai dòng cuối cùng của bạn có thể được rút ngắn thànhprint"\n".join(r[::N>0 or-1])
Steven Rumbalski

@Steven Tôi đã thay đổi. Cảm ơn bạn.
Ante

1

Perl, 113 ký tự

$i=abs($I=<>);@w=$_='_'x3**$i;while($i--){$x=3**$i;s/(__){$x}/'_'x$x.' 'x$x/eg;push@w,$_}say for$I>0?reverse@w:@w

Mở rộng:

$i=abs($I=<>);
@w=$_='_'x3**$i;
while($i--){
    $x=3**$i;
    s/(__){$x}/'_'x$x.' 'x$x/eg;
    push@w,$_
}
say for$I>0?reverse@w:@w

1

JavaScript 121 byte

Hàm đệ quy bên trong, sau đó chăm sóc đầu ra ngược nếu cần

n=>(f=(n,t=n&&f(n-1),r=t[0])=>n?[r+r+r,...t.map(x=>x+t[n]+x)]:['_',' '],f=f(n<0?-n:n),f.pop(),n<0?f.reverse():f).join`\n`

Ít chơi gôn

n=>{
  var f = n => { // recursive function
    var t = n && f(n-1), r = t[0]
    return n 
      ? [r+r+r, ...t.map(x => x+t[n]+x)]
      : ['_',' ']
  };
  f = f(n < 0 ? -n : n);
  f.pop(); // last row is all blanks
  if (n<0) f.reverse();
  return f.join`\n`
}

Kiểm tra

var F=
n=>(f=(n,t=n&&f(n-1),r=t[0])=>n?[r+r+r,...t.map(x=>x+t[n]+x)]:['_',' '],f=f(n<0?-n:n),f.pop(),n<0?f.reverse():f).join`\n`

function go()
{
  var n=+I.value
  O.textContent = F(n)
}

go()
<input id=I type=number value=3 oninput='go()'>
<pre id=O></pre>


1

Hàng loạt, 265 262 242 236 235 byte

@echo off
set/pn=
set c=%n%,-1,0
if %n% lss 0 set c=0,1,%n:-=%
for /l %%i in (%c%)do call:l %%i
exit/b
:l
set s=_
for /l %%j in (1,1,%n:-=%)do call:m %1 %%j
echo %s%
:m
set t=%s%
if %1 lss +%2 set t=%s:_= %
set s=%s%%t%%s%

Chỉnh sửa: Đã lưu 12 19 byte nhờ @ l4m2. Đã lưu 8 byte bằng cách loại bỏ %a%biến không cần thiết .



@ ConorO'Brien Hãy nhớ rằng bạn sẽ là 261 nếu tôi đếm tất cả các CR cũng như các LF (mà tôi chắc chắn rằng bạn không bắt buộc phải làm nhưng tôi lười như thế).
Neil

Vì vậy, bạn không xóa CR khỏi mã của bạn? Mặc dù nó không được yêu cầu bởi các tệp .BAT và bị tước bởi SE bằng mọi cách? : P
Conor O'Brien

@ ConorO'Brien Đó là một hình phạt tôi chấp nhận sử dụng Notepad để ghi các tệp Batch.
Neil

Bạn có thể làm một cái gì đó như thế set c=%n%,-1,0 [LF] if %n% lss 0 set c=0,1,%a% [LF] for /l %%i in (%c%)do call:l %%inào?
l4m2



0

Prolog (SWI) , 265 232 213 byte

S-E-R:-between(S,E,R).
[]/R/R.
[H|T]/B/R:-T/[H,32,H|B]/R.
N+R:-(N>0->O is N-1,O+S,S/[]/R;R=`_`).
N*[H|T]:-1-N-_,writef("%n",[H]);N*T.
_*[]:-nl.
-N:-(0-N-J,K is N-J;N-0-I,J is -I,K is I-N),L is 3^K,J+R,L*R,1=0;1=1.

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


0

PowerShell , 111 byte

filter f{if($s=[math]::Sign($_)){($x=$_-$s|f|%{$_+' '*($l=$_|% Le*)+$_})|?{$s-1};'_'*3*$l;$x|?{$s+1}}else{'_'}}

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

Ít chơi gôn hơn:

filter f{
    if($sign=[math]::Sign($_)){
        $x=$_-$sign|f|%{
            $_+' '*($length=$_|% Length)+$_
        }
        $x|?{$sign-1}  # output $x if $_ is negative
        '_'*3*$length
        $x|?{$sign+1}  # output $x if $_ is positive
    }
    else{
        '_'
    }
}
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.