カントールセットを印刷する


19

チャレンジ

Nレベルのキャンターセットを作成します。

Cantorターナリセットは、一連のラインセグメントのオープンミドル3分の1を繰り返し削除することによって作成されます。

プログラムは1つのパラメーターN(整数)を受け取り、NレベルのCantorセットを(コンソールまたは同様の方法で)印刷します。印刷には、アンダースコア(_)と空白文字のみを含めることができます。パラメータは正でも負でもかまいません。記号はカンターセットの構築方向を示します。N > 0カンターセットが下向きに構築されN < 0、カンターセットが上向きに構築されている場合。その場合N = 0、プログラムは1行(_)を出力します。

例えば:

N = 2

_________
___   ___
_ _   _ _

N = -2

_ _   _ _
___   ___
_________

N = 3

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

N = -3

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

受賞基準

それはコードゴルフの挑戦なので、最短のコードが勝ちます。

編集:ugorenの提案により0入力を変更します。


N = 0のときに何も印刷しないのはなぜですか?これにより、0が特別なケースになり、再帰の使用が難しくなります。一般的な処理は、1つを印刷する_ことです(ただし、-0を取得する場合は下方向に印刷します)。
ウゴレン

右。すでに仕様を変更しました。
アベロス

回答:


10

GolfScript、49 42 40文字

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

42-> 40のハンマーに感謝します。

さらに数論的なアプローチでの私の最善の試みは、悲しいことにはるかに長いです:

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

または

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

そして、私はその長さが追いつくことを不可能にするbaseと疑いzipます。


~.abs.@/\.3\?'_'*\{.3%..,' '*\++}*](%n*39文字ですが、入力時にクラッシュします0。:-(
イルマリカロネン

それはあなたが行うことができないものであるため@IlmariKaronenは、はい、ゼロによる除算は、私も書いたCの実装のための痛みだっn/abs(n)取得しますsignum(n)
ピーターテイラー

6

Python、116 113 104 103文字

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

古いアルゴリズムは113文字でトップになりました

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

ルビー(97)

Steven Rumbalskiのpythonバージョンに基づく:

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

以前の試行、両方とも同じ長さ(112)

部品からラインを作成します。

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

1行から始めて、そこに穴を開けます。

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文字

@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

私は、Peter TaylorのGolfScriptソリューションがPerlにどれだけうまく移植できるかを試してみたいと思いました。注目すべき機能には、スペースが前にソートされるという事実を使用して、3文字を保存するsort代わりにの使用が含まreverseれます_


2

Common Lisp、217 210文字

(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)))))

拡張:

(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)))))

Lispコードが他の言語の初期カウントを打ち負かすことができたかどうかを考えます(C、219)私は大丈夫です:)


2

C(163161文字)

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);}

ugorenの答えからいくつかのトリックを借りますが、コアロジックはかなり異なります。私は彼のforループをフォローできなかったので、ハイブリッド化してさらにいくつかを保存することが可能かもしれません。


2

C、219 193 179 143 136 131文字

Petyer Taylorの別のアイデアに従い、さらに私自身の改善により、さらに6つ節約できました。
@PeterTaylorからのヒントをいくつか統合し、主な機能を少し変更してコピーしました。これにより、キャラクターを救うことができます(コピーするのは公平でしょうか。
私は再帰がどのように機能するかを大幅に改善することを考え、ピーターテイラーの答えを見た後、リードを取り戻すためにそれを実装しました。再び彼の答えを読んだとき、私は彼がしたことをほぼ正確にしたことがわかりました。だから、これは彼が提案した交配のようだ。
また、のループを単純化しmain、同じ長さを維持しました。
そして、代わりに改行を印刷するためにピーターのトリックを取りましたputs("")-キャラクターを保存します。

int変数宣言から削除-警告ですが、4文字を節約します。
新しいアルゴリズムは事前に3 ^ xを計算しませんが、1つのループを使用して3 ^ x文字を印刷します。
を定義することint*vでもう1つ保存できますが、64ビットは機能しません。
文字数には空白が含まれません(削除可能)。

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("");
}

古いアルゴリズム、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、iパラメーターを削除することはできませんmain。グローバルを使用するとに干渉するためです。l--に干渉しo>=lますが、私はそれを置き換える必要があります>(だから、あたかもそれが悪いことのように書くのですか?)私もあなたmainよりコピーできます。
-ugoren

@PeterTaylor、あなたは正しかったi-私はもうそれを実際に使用していないという事実を見逃した(私はあなたが私がそれを渡さないことを意味すると思った)。
-ugoren

ちなみに、あなたが私の主な役割を引き受けても構いません。私の経験則では、他の誰かのソリューションをコピーして単一の文字を変更することは過度に攻撃的であり、他の誰かのソリューションをコピーしてその半分を書き換えることは完全に公平であり、中間には灰色の領域があります。おそらく、メタに関するいくつかのコミュニティ標準に同意する必要があります。
ピーターテイラー

@PeterTaylor、ある種の行き詰まりに達したと思う。私pは今、かなり最適だと思われ、あなたのmain方が良かったです(最適かどうかはわかりませんが、それ以上改善できません)。したがって、新しい独創的なプログラム構造を除いて、進むべき唯一の方法は、どちらか一方が他方のコードをコピーすることでした。
-ugoren

ところであなたはキャラクターをどうやって数えていますか?私は、ない136最新バージョンの138文字を作るので
ピーター・テイラー

2

J、44 39 38 37バイト

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

反復を使用して、_最初に1(を表す)で始まる次のセットを構築します。

使用法

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

説明

' _'{~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

いいね!私は個人的に試していないが、議題を使用して、私の愛は@.それを--perhaps、と組み合わせて$:、ここでいくつかの使用のだろうか?たとえば、次のようなもの(zero case)`(positive case)`(negative case)@.*、または多分":@_:`(positive case)`(|."1@$:)@.*
コナーオブライエン

再帰的な解決策は試していませんが、試してみました。
マイル

2

R141の139 137バイト

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,,"")

オンラインでお試しください!

-15バイトもGiuseppe '('がID関数として使用していることに感謝します。出力を印刷するwrite代わりにcat; の巧妙な使用%x%

アイデンティティ関数としてのc代わりに使用することにより、キリルL.に感謝-2バイト'('


ここでクロネッカー製品が機能しますか?%x%?...多分、交互の行を取るといくつかの問題があるかもしれません
ジュゼッペ

@Giuseppe私はあなたの「より小さい「H」から「H」を作成する」答えに基づいて試みました...私はそれにもう一度試してみます。
JayCe

ああ、だからそれを支持したのはあなただった。それが私が考えた唯一の理由kronです!適切なアプローチを見つけることができれば、これで125バイトまで下がることができると思います。
ジュゼッペ

`(`アイデンティティ関数として使用できるため、ループのwrite代わりに直接使用できます。141バイトcatfor
ジュゼッペ

@Giuseppe私は、(この方法で使用できるとは思いもしなかっif たし、2つの関数から選択するのにも使用できなかった。そして、私は書き込みの使用を開始します...多くの「\ n」を節約します。
JayCe

1

Python、177 164文字

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

Python 2を使用しているため、inputas の結果をキャストする必要はありませんint。あなたの最後の2行はに短縮することができprint"\n".join(r[::N>0 or-1])
スティーブンRumbalski

@Steven変更を加えました。ありがとうございました。
アンテ

1

Perl、113文字

$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

拡張:

$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バイト

内部再帰関数、必要に応じて逆方向出力を処理します

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`

少ないゴルフ

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

テスト

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

バッチ、265の 262 242 236 235バイト

@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%

編集:@ l4m2のおかげで12 19バイトを保存しました。不要な%a%変数を削除して8バイトを保存しました。


これは247バイトです。
コナーオブライエン

@ ConorO'Brienは、LFと同様にすべてのCRを数えると261になることに注意してください(これはあなたがする必要はないと確信していますが、私はそのように怠け者です)。
ニール

コードからCRを削除していませんか?.BATファイルで必要ではなく、SEで削除されたとしても?:P
コナーオブライエン

@ ConorO'Brienメモ帳を使用してバッチファイルを書き込むことは、ペナルティです。
ニール

次のようなことができますset c=%n%,-1,0 [LF] if %n% lss 0 set c=0,1,%a% [LF] for /l %%i in (%c%)do call:l %%iか?
l4m2




0

PowerShell、111バイト

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

オンラインでお試しください!

少ないゴルフ:

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{
        '_'
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.