ユニバーサルバイナリ関数のルックアップテーブルを生成する


19

これは難解なプログラミング言語発明しようとする私の探求に正接しています。

2進数のテーブル0 .. 15を使用して、インデックス操作を使用してユニバーサルバイナリ関数を実装できます。2つの1ビット入力XおよびYが与えられた場合、16の可能な関数すべてを 4ビットのオペコードでエンコードできます。

X Y  F|0 1 2 3 4 5 6 7 8 9 A B C D E F
- -    - - - - - - - - - - - - - - - -  
0 0    0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1    0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0    0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
1 1    0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
       -     -   - -   -   -   -   - -
       0    ~X  ~Y ^   &   Y   X   | 1
      ZERO    NOT-Y   AND         OR
          NOT-X   XOR              ONE

したがって、この16個の関数のセットは、関数としてバイナリ入力に適用できます。

U(f、x、y):(f >>((x << 1)| y))&1

または

U(f、x、y):(f / 2 ^(x×2 + y))%2

または、インデックス付けまたはマトリックス分割を使用します。

このタイプのバイナリ演算に基づいて構築される可能性のある言語に対して、このような値の表を表現または生成する最もコンパクトな方法を知っていると便利です。

目標:

この正確なテキスト出力を生成します。

0101010101010101
0011001100110011
0000111100001111
0000000011111111

それでおしまい!最短コードが勝ちます。


2
私は、APLファミリーがここでうまくいくだろうという直感を持っていました。:)
luser droog


先頭または末尾の改行は受け入れられますか?
タイタス

はい、余分な改行は問題ありません。
luser droog

回答:


20

J、10(13?)文字

|.|:#:i.16

番号リスト:

   i.16
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15`

バイナリへ:

   #:i.16
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1

転置:

   |:#:i.16
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

逆:

   |.|:#:i.16
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

スペースを削除する必要がありますか?他のJの回答を見ると、3文字追加1":してJanの回答から借用する必要があるようです。


1
説明の非常に素晴らしいスタイル。+1(短い!)
luser droog

PeterのGolfscriptの回答を見るとすぐに、もっとうまくやれると思いました。まあ、あなたはすでにそれをやっていました。
ジョン・ドヴォルザーク

ニースは... Golfscriptより短いものを見るために
fuenfundachtzig


@luserdroogうわー。それはたくさんのコードです。ただし、Jソースコードよりもはるかに読みやすくなっています。:-) とてもかっこいい。
ガレス14年

13

Python 2、40

for n in 1,2,4,8:print 8/n*('0'*n+'1'*n)

7

APL(14)

想定⎕IO=0(設定):

⎕D[⊖(4⍴2)⊤⍳16]

説明:

  • ⍳16:数字[0,16)
  • (4⍴2)⊤:4桁を使用して基数2の各数値をエンコードします
  • :水平反転(MSBが最上部に配置されます)
  • ⎕D[... ]:これらの値から⎕D文字列を選択します0123456789。(数値マトリックスは値の間にスペースを入れて表示されますが、文字マトリックスはそうではありません。したがって、これは各数値ビットをcharsの1つに変換します'0' '1')。

ソースの最初の文字は正方形のように見えるはずですか、それともまだいくつかのフォントがありませんか?
ティムセギーン14年

@TimSeguineはい、APL文献ではクワッドと呼ばれる正方形です。quadで始まる変数名は、環境を変更するシステム変数です。IO =「インデックスの原点」。
luserはドローグ

バイトを保存:(4⍴2)⊤2⊥⍣¯1
アダム

6

ゼリー42 7 バイト(非競合)

⁴ḶBUz0Y

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

デニスの協力に感謝します。これが最初のメッセージ、ここが最後です(他の議論も行われました)。彼の助けを借りて、私は明らかに(ほぼ)スコアを平方根化した。


言語は質問よりも新しいため、回答として受け入れることはできません。確かに、賞金のためのランニングで、カントー!
luserはドローグ

@luserdroogそれは結構です。しかし、私は挑戦が新しいと思いました。
エリックアウトゴルファー

私はあなたが何を意味するか知っています、それを私がそれを投稿したのはずっと前のように感じません。しかし、2歳の私自身のinca2でさえ、言語としては若すぎます。
luserはドローグ

42対7のコードゴルフでは+1。これは、(意図的に行わない限り)毎日表示されるものではありません。
ケビンCruijssen

1
@KevinCruijssenなぜそれが意図的に行われるべきなのですか?私はただのゼリー初心者です(Python 2と3をよく知っています)ので、「ゼリーを配列操作言語として扱う必要がある」間、私はそれを文字列でやりました。
エリックアウトゴルファー


4

GolfScript(18 17 15文字)

(ハワードのおかげで)

16,zip{','-~n}%

なぜ10文字なのか分かりません

16,zip{n}/

動作しません。標準インタープリターのバグにより、スタック上でサポートされていない型が発生していると思われます。

私が完全に理解している18文字の代替案は次のとおりです。

4,{2\?.2,*$8@/*n}%

より数学的なアプローチは少し長く、28文字です。

4,{2.@??)2.4??.@/+2base(;n}/

その多くは、基本変換とゼロパディングのためです。これらがないと、19文字になりますが、

4,{2.@??)2.4??\/n}/

出力付き

21845
13107
3855
255

正確なテキスト出力を求められました-なぜ16,zip{n}/機能するのですか?
ハワード

一方、できること16,zip{','-~n}%
ハワード

@Howard、zip配列の配列を返すべきだと思いますが、実際にはRuby配列の配列を返すようです(私の推測では最高です)。要素が何であれ、それらに `` `` `を適用しても、印刷方法には影響しません。これは、4つのGolfScriptデータ型のいずれとも異なります。あなたは正しい','-です、それはそれらを通常の配列に変えるようです:素敵なトリック。
ピーターテイラー

ここでゼロの4つの余分な行を出力するようです
aditsu

@aditsuは、オンラインデモに取り組んでいます。なぜ違いがあるのだろうか。多分Rubyバージョン?
ピーターテイラー

3

CJam-16

4,{G,f{\m>2%}N}/

同等のJavaコード(説明として):

public class Lookup {
    public static void main(final String... args) {
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 16; ++j) {
                System.out.print((j >> i) % 2);
            }
            System.out.println();
        }
    }
}

3

Javascript(ECMA6)、67

s=(k,n)=>n-.5?s((k<<n/2)^k,n/2)+"0".repeat(n)+k.toString(2)+"\n":"" 

これを使用するには、呼び出します

s(255,8)

ビットシフト!
また、XORと少しの再帰。

最初に注意することは、任意の行を取得し、それを(連続する0の数)/ 2左にシフトすると、次の行を取得するための素晴らしいXORが得られることです。

例えば、

0000000011111111 //line 4
0000111111110000 //shifted 4 to the left

これらのビット単位のXOR

0000111100001111 //XOR'ed. This is line 3!

次の行(3行目)です。
3行目に同じプロセスを適用し、左に2をシフトすると、...

0000111100001111
0011110000111100

XOR'edが与える

0011001100110011

これは2行
目です。シフトする量は毎回半分になることに注意してください。
ここで、2つの引数を使用して、この関数を単に再帰的に呼び出します。この行の整数値、およびN(シフトする必要がある量)。再帰を行うときは、シフトされたXORされた値とn / 2を渡すだけです。

"0".repeat(n)

toStringは先頭の0を取り出すため、各行の先頭に0を埋め込みます。


+1とてもクール。以前そのパターンに気づいていませんでした。
luser droog 14年

:カップル不戦勝は、ビットがNシフトの代わりにそれを分割し、テンプレート文字列を使用して新しい行を交換することによって、この遮断することができるs=(k,n)=>n?s((k<<n/2)^k,n>>1)+"0".repeat(n)+k.toString(2)+` `:""
ショーンH

2

J、21文字

1":<.2|(2^i.4)%~/i.16
  • i.16 0..15のリストです
  • 2^i.4 リスト(1,2,4,8)
  • %~/ 左の引数は行を形成するが、除算の右の引数である除算表を生成します
  • 2| [各セル]を2で割った後の余りを計算します
  • <. 0または1に値するフロア
  • 1": セルごとに1文字でテーブルをフォーマットします

私はfloor必要ではないように感じています。のドメイン2|は既に0または1です。
luserはドローグ

@luserdroog |はfloatで動作します。2|3.25です1.25。私たちはそれを望んでいません。
ジョンドヴォルザーク


2

ルビー(44)

退屈で長い:数字の0が埋め込まれたバイナリ表現を印刷するだけです。

[21845,13107,3855,255].map{|i|puts"%016b"%i}

2

追記 108 177 126 77 74 70

[43690 52428 61680 65280]
{16{dup 2 mod =only 2 idiv}repeat<>=}forall

より単純なmod- offメソッドの値を逆にしました。

151 131 119

よりAPLに近いアプローチを適用します。編集:文字列のチョッピングと配列のジッピングをインデックスとforループに置き換えました。

[[0 1 15{}for]{16 add 2 5 string cvrs}forall]4 
-1 1{0 1 15{2 index exch get 1 index 1
getinterval =only}for pop<>=}for

インデント:

[[0 1 15{}for]{16 add 2 5 string cvrs}forall]
4 -1 1{ % [] i
    0 1 15{ % [] i j
        2 index exch get % [] i [](j)
        1 index 1  % [] i [](j) i 
        getinterval  % [] i [](j)<i>
        =only  % [] i
    }for 
    pop<>= % []
}for

受賞したJの回答で使用されている関数を再実装すると、これにつながります(多くのサポートコード)。

-1 16 i + #: |: |.{{==only}forall()=}forall

iここで、1-基づいてベクトルはアイバーソンの中で説明した初等関数、したがって、-1 ... +生産します0 .. 15


2

Perl(36 + 1)

say通常どおり、に対して+1 。ダブル0はタイプミスではありません:)

map say((00x$_,1x$_)x(8/$_)),1,2,4,8

に1を追加する必要はありませんsayperl -e'...'これは標準であり、これにはが必要perl -E'...'です。バイト数の増加はありません。とにかく、無料のCode Golf Metaで決定されたと思います-M5.01
msh210

2

JavaScript(ECMA6)、108

ここで別のアプローチを試してください。バイナリ演算子を使用することをお勧めしましたが、チャレンジもあり、私は考えていたので、このソリューションを提出することを許可しました-それらの値を表すコードの量をどのように減らすことができますか...?拠点

['gut','a43','2z3','73'].forEach(n=>{a=parseInt(n,36).toString(2);
alert(('00000000'+a).substr(a.length-8))})

(便宜上、改行)。

先行ゼロでパディングを台無しにする必要があったのは残念ですが、このコードのポイントは単にBase 36のターゲットバイナリの結果を表しているだけです。 gut, a43, 2z3, 73です。

注:私はそれが勝ちの答えの近くにどこにもないことを理解していますが、アイデアのためだけに...


1
私はあなたのものを見たときに基本的に同じことをしようとしていました。同様の質問への私の答えからのテクニックを使用して、92バイトにしました:alert(['gut','a43','2z3',73].map(n=>(1e8+parseInt(n,36).toString(2)).slice(-16)).join('\n'))。このアプローチでは、4 alert()秒ではなく改行を使用します。
NinjaBearMonkey




2

JavaScript(ES6)、58 52バイト

文字列を再帰的に構築します。

f=(n=64)=>n--?f(n)+(!n|n&15?'':`
`)+(n>>(n>>4)&1):''

使い方

この再帰は、パターンがニブル0x0〜0xFの垂直バイナリ表現で作られているという事実に基づいています。

  0101010101010101 bit #0 <- Y = 0
  0011001100110011 bit #1
  0000111100001111 bit #2
  0000000011111111 bit #3 <- Y = 3
  ----------------
  0123456789ABCDEF
  ^              ^
X = 0          X = 15

したがって、このパターンの各位置(X、Y)は、X:のY番目のビットとして表すことができますX & (1 << Y)。このビットを次のように分離することもできます(X >> Y) & 1。XとYを追跡するのではなく、0〜63のn範囲の単一の変数を反復処理します。したがって、式は次のようになります(n >> (n >> 4)) & 1。実際には、63から0に反復する方が簡単なので、文字列は逆の順序で作成されます。つまり、文字n-1は文字nの左に追加されます。

副次的な注意として、再帰はここでは短いコードを除いて何ももたらしません。

改行なしの場合、コードの長さは35バイトです。

f=(n=64)=>n--?f(n)+(n>>(n>>4)&1):''

改行を挿入するには、さらに17バイトが必要です。先頭の改行が許容される場合、これは14バイトに短縮できます。

デモ

f=(n=64)=>n--?f(n)+(!n|n&15?'':`
`)+(n>>(n>>4)&1):''

console.log(f());


1がより聞かせてあり、上記の両方の言語でideoneではJavaScriptはそれは良いが... 1つの再帰関数の考えです.... exapmeにコンパイルされない
RosLuP

35バイトの後に分割するには何が必要ですか?
タイタス

@タイタス-まあ。一見したところ、それに対する良い解決策はありません。(非常に悪い)試みはここにあり(f=(n=64)=>n--?f(n)+(n>>(n>>4)&1):'')().match(/.{16}/g).join`\n` ます:(63バイト)
-Arnauld

うーん...そして.replace(/.{16}/g,"$0\n")同じ長さを持っています。残念な。
タイタス


1

NARS2000 APL、22

"01"[⊖1+(4⍴2)⊤(⍳16)-1]

marinusのAPL回答から派生したもので、NARS2000では機能しないようです。

ベクトルを生成

      ⍳16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

ゼロベースに変更

      (⍳16)-1
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

エンコード用の形状を生成

      (4⍴2)
2 2 2 2

エンコード

      (4⍴2)⊤(⍳16)-1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

1ベースのインデックス作成の調整

      1+(4⍴2)⊤(⍳16)-1
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2

主軸を反転

      ⊖1+(4⍴2)⊤(⍳16)-1
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2

索引

      "01"[⊖1+(4⍴2)⊤(⍳16)-1]
0101010101010101
0011001100110011
0000111100001111
0000000011111111

⎕IOを0に設定すると、1ベースのインデックス作成を調整する必要がなくなります。これにより、16文字になります。
エリアスマーテンソン14年

はい、しかし、私はそれが他のAPLの答えとあまりにも似ているのではないかと恐れており、まったくここにいるに値しないでしょう。
luserはドローグ

1

C、73文字

i;main(){for(;i<64;)i&15||puts(""),putchar(48|1&~0xFF0F0F33335555>>i++);}

これは、4つの16ビットブロックで64ビットを出力するための一般的なソリューションです。0xFF0F0F33335555他のビットシーケンスを出力するには、数値を変更するだけです。

簡略化された&なし

int main() {
    int i;
    for(i = 0; i < 64; i++) {
        if(i % 16 == 0) {
            puts("");
        }
        int bit = ~0xFF0F0F33335555 >> i;
        bit &= 1;
        putchar('0' + bit);
    }
}

1

ハスケル、73

Yikes、73文字!しかし、神の愛のためにこれを小さくすることはできません。

r=replicate
f n=r(div 8n)("01">>=r n)>>=id
main=mapM(putStrLn.f)[1,2,4,8]

これに関する本当に悲しい部分は、bashを使用して出力をエコーする場合、74文字しか必要ないということです。



1

inca233 27 24

4 16#(,`2|(~16)%.2^~4){D

これはJan Dvorakの回答に基づいています。inca2は、昨日のバグ修正時点でこれを実行できます。言語は、質問後に発明されたので、技術的には無効、しかし言語の発明は、質問を装っにおける私の目標の一部でした。それで、他の回答に対する感謝の報いがあります。:)

説明:

4 16#(,`2|(~16)%.2^~4){D
          (~16)               integers 0 .. 15 
                 2^~4         first 4 powers of 2: 1 2 4 8
          (~16)%.2^~4         division table
        2|                    mod 2 (and floor)
       `                      transpose
      ,                       ravel
     (               ){D      map to chars '0'..'9'
4 16#                         reshape to 4x16

括弧のいくつかは不要なはずですが、どうやら文法の解釈にはいくつかの問題が残っているようです。そして、「ラベル=>マップ=>変形」は本当に不器用です。マップはもっとスマートにする必要があります。編集:バグ修正により、括弧を削除できます。


基本変換を個別の関数に分解すると、N:x|y%.x^~1+[]/x.yこれが得られます19 16文字バージョン。

4 16#(,`2N~16){D

とにかくここで不正行為をしている間、私は先に進み、これを組み込み関数にしました。しかし、たとえそれがニラディック関数(引数を必要としない)であっても、ニラディック関数はサポートされていないため、仮引数を指定する必要があります。

inca2、2

U0

1

Pyth 24/26

最短の方法はgrcの答えでしたをPythに翻訳したもので、安いと感じたため、独自の方法を実行しました。

鉱山:26文字

 mpbjk*/8dS*d[0 1)[1 2 4 8

grc's:24文字

Fd[1 2 4 8)*/8d+*\0d*\1d

1

C ++ 130

16進数をバイナリに変換します

#define B std::bitset<16>
#define C(x) cout<<x<<endl;
void main(){
B a(0xFF),b(0xF0F),c(0x3333),d(0x5555);
C(d)C(c)C(b)C(a)
}

1

Haskell(ラムダボット)、47バイト

unlines$reverse$transpose$replicateM 4['1','0']

それは使用しているのでちょっとcheaty 転置 Data.ListとからreplicateM Control.Monadからの、しかし両方Lambdabotからデフォルトでロードされています。

また、改善の余地があると確信しています。アイデアを共有したかっただけです


1

ジュリア(39バイト)

私がジュリアで書いた2つ目のスクリプトは、ジュリアが好きだと認めなければなりません、彼女はかなりの獣です。

hcat(map(x->collect(bin(x,4)),0:15)...)

返品

[0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 
 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]  

説明:

  • bin(x,4) -intを4文字にパディングして2進整数に変換します。
  • collect(_) -文字列をchar配列に分割します。
  • map(x->_,0:15) -範囲内の最初の16桁に対してこれを行います。
  • hcat(_...) -スプラットし、水平方向に連結してマトリックスにします。

1

C 83 77 76 74 71

x;f(n){for(;x<4;x++,puts(""))for(n=0;n<16;)putchar(49-!(n++&(1<<x)));}

とても簡単です。

x;
f(n){
    for(;x<4;x++,puts(""))
        for(n=0;n<16;)
            putchar(49-!(n++&(1<<x)));
}

1
を使用しないことで2の簡単な節約があり?:、を移動することで1の節約があり++ます。
ピーターテイラー

に変更mainして3を保存しましたf。lol
luser droog

1

R、53 41バイト

@grcのpython回答の翻訳。の引数と引数rep()の使用(および引数の部分一致)を使用して、元の翻訳から12バイトを削り、それがと同等であることを覚えておいてください。eachlength0:1c(0,1)

for(n in 2^(0:3))print(rep(0:1,e=n,l=16))

for(n in 2^(0:3))print(rep(c(rep(0,n),rep(1,n)),8/n))

次のような@GarethのJ回答の翻訳を試みることもできます(34バイト):

t(e1071::bincombinations(4))[4:1,]

ただし、ベースRの一部ではない関数を使用し、仕様のように正確な印刷テキストにフォーマットするのが難しい行列を出力します。

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