MATLでのゴルフのヒント


20

MATLは、ルイスメンドーによって作成されたゴルフ言語です。MATLは非常に競争力があることが証明されており、多くの場合、Pyth、CJam、Jellyなどの他のゴルフ言語での提出物に勝っています。

MATLでゴルフをする際に役立つヒントは何ですか?(いつものように、回答ごとに1つのヒントをお願いします!)


5
Matlab / Octaveを知っているなら、間違いなく大きな利点です。いくつかのトリックMATLABでゴルフのヒントオクターブにゴルフのためのヒントは、あまりにもMATLで使用されます。
flawr

提案:()は非常に強力なように見えますaccumarrayXQこれらの長さ関数ハンドルには便利な数値コードがあるため、おそらくMATLAB / Octaveよりも強力です)が、良い例で説明するのに十分なことはわかりません。それが実際に有用な場合、誰かがそれを使用する方法についてのアイデアで答えを作成できますか?
スンダ

回答:


7

事前定義されたリテラルを知る

それらの一部は、クリップボードにコピーされるときに情報を保持しますが、すべて事前に定義された値を持っています。

  • F0をプッシュ(実際はFalse
  • T、プッシュ1(実際にはTrue
  • H、プッシュ2(事前定義されたクリップボード値)
  • I、プッシュ3(事前定義されたクリップボード値)
  • K、プッシュ4(事前定義されたクリップボード値)
  • J0 + 1jをプッシュ(事前定義されたクリップボード値)

ただし、すべての定義済みの値を網羅しているかどうかはわかりません。


完全を期すために(また、答えに追加したい場合):クリップボードの各レベルにはL定義済みの値もありますが、(一般的な一般的な値ではなく)特別な使用を目的としています。たとえば、1Lギブス[1 0](インデックスとして使用1:end)、2Lギブス[0 -1 1](for 1:-1:end)。また、デフォルトでは機能しlO0入力を取り01それぞれを生成します
ルイスメンドー

私はこれがどのように役立つかわかりません...ただ書くことはできません4
チョイス

@Cyoce有用なのは、区切り文字としてスペースを使用しないことです。をプッシュしたい場合1414実行しません。あなたが必要だろう1 4。または1K1バイトを保存するには
ルイスメンドー

@LuisMendoああ、なるほど。私はそれが1桁の数字のみの方法を使用していたと推測したと思います(理由は
わかり

1
K代わりに4便利なもう1つのケースは次のとおりです。1-4手段:push 1、次にpush -4; 一方、1-Kプッシュ1、スタックの下にあるものから減算し、プッシュ4
ルイスメンドー

5

&メタ関数(代替入力/出力仕様)

関数に渡す入力引数の数を指定する従来の方法は、$メタ関数を使用することです

2$:     % Two-input version of :

同様に、出力引数の数を指定するには、出力引数の数を指定する#メタ関数を使用できます。

2#S     % Two-output version of sort

または、関数に定義された出力引数の数よりも大きい数を渡すと、出力のみmod(N, numberOfOutputs) + 1が提供されます。

4#S     % Get only the second output of sort

さらに、入力として論理配列を指定して、#特定の出力引数のみを取得できます。

TFT#u   % Three output version of unique and discard the second output

これらの入力/出力仕様はすべて便利です、バイトカウントを非常に迅速に増加させます。これに対処するため、MATL &17.0.0リリースでメタ関数を導入しました。この&メタ関数は、関数の特定の入力または出力仕様へのショートカットとして機能します。それが何を意味するのか見てみましょう。

上記の例では、2入力バージョン:(等間隔の値のベクトルを作成します)を使用します。への入力引数のデフォルト数:1(から配列を作成する[1...N])ですが、ユーザーが2番目の入力を必要とする範囲の開始値を指定することは非常に一般的です。そのため:&のショートカットと定義しました2$

10      % Push 10 to the stack
12      % Push 12 to the stack
2$:     % Create an array: [10, 11, 12] 

今、次のようになり、バイトを保存します

10 12 &:

引数の代替数はどのように決定できますか?

&変換する入力/出力仕様は、バイト節約を最適化するように機能固有です。

各関数のヘルプの説明の入力/出力引数セクションが更新され、この代替入力/出力の数(存在する場合)が示されます。入力または出力引数の可能な数は範囲として表示され、それぞれのデフォルト値は括弧内に表示されます。置換可能な入出力仕様&/、括弧内の文字の後に表示されます。

以下は、ヘルプの説明の入力/出力引数セクションです。 :

 +- Min-Max range of # of inputs
 |        +----- Alt. Default # of inputs
 |        |
 V        V
1--3 (1 / 2); 1 <--- Possible / Default # of outputs
      ^       
      |       
  Default # of inputs

&各機能の意味をどのように判断しましたか?

非常に慎重に。使用StackExchangeのAPIを、私たちはこれまでPPCGチャレンジで使用されているすべてのMATLの答えをダウンロードすることができました。各回答を解析することにより、各機能に各入力/出力仕様が使用される頻度を決定することができました。この情報を使用して、&メタ関数が各関数に対して表す必要がある入力/出力仕様を客観的に識別することができました。明確な勝者がいない場合があるため、現在多くの機能が&定義されていません。

使用したスクリプトは次のとおりです(残念ながら、MATL ではなく MATLABで作成されてます)。

そして、これ$/ #使用法のヒストグラム例です


1
この機能は@Sueverによって提案されました。元々&は、「デフォルトに対して入力の数を1増やす」ことを意味していました。彼の提案は、はるかに有用であることが判明
ルイスMendo

5

MATLの真実/偽の定義に精通する

一方でtrueT)とfalseF)は明らかに、それぞれ、truthyとfalsy出力を表し、truthy / falsyの広く合意された定義は、私たちにMATLでもう少し柔軟性を提供します。

定義の状態:

if (x)
    disp("x is truthy");
else
    disp("x is falsy");
end

したがって、すべての入力をループし、それらが真実であるか偽であると見なされたかを表示する、簡単なMATLの真実/偽のテストを書くことができます。

` ? 'truthy' } 'falsey' ]DT

こちらがオンライン版です。

これがMATLで意味すること

これが実際にMATL(したがって、MATLABおよびOctave)に変換されるのは、空でなく、そのすべての値の実コンポーネントがゼロでない場合、条件は真であると見なされるということです。これには、強調すべき2つの部分があります。

  1. ゼロ以外:これは、ゼロではないことを正確に意味します(==)。これには、正の数、負の数、非ヌル文字などが含まれます。特定の値を値に変換することで簡単に確認できlogicalます(g)、または~~

    F           % Falsy
    T           % Truthy
    0           % Falsy
    1           % Truthy
    2           % Truthy
    -1          % Truthy
    'a'         % Truthy
    ' '         % Truthy (ASCII 32)
    char(0)     % Falsy  (ASCII 0)  
    
  2. すべての値:通常、スカラーはtrueまたはfalseであると考えますが、MATLでは、スカラー、行ベクトル、列ベクトル、または多次元行列でさえも評価できます。ゼロ以外(上記で定義)、そうでない場合は偽です。ここにいくつかの例を示します

    [1, 1, 1]           % Truthy
    [1, 0, 0]           % Falsey
    [1, 1, 1; 1, 1, 1]  % Truthy
    [1, 0, 1; 1, 1, 1]  % Falsey
    'Hello World'       % Truthy
    

前述のように、1つのエッジの場合は空の配列で[]、常に偽と見なされます(

これをどのように使用してゴルフを改善できますか?

課題が出力が真実または偽であるべきであると単純に言及している場合、おそらく上記の定義を活用して、回答から数バイト削り取ることができます。混乱を避けるために、上記のオンラインの真実/偽のテストへのリンクを回答に含めて、MATLの真実/偽の値がどのように機能するかを説明することをお勧めします。

いくつかの具体例:

  • で終わる回答A。挑戦はtruthyまたはfalsy出力を必要とし、あなたがあなたの答えを終了した場合allAスカラーを作成するために)、あなたはこの最後のバイトを削除することができますし、(出力されない限り、あなたの答えが正しい残ります[]ので、[]ですfalseが、[]Aですtrue)。

  • 配列に一意の値が1つだけ含まれることを確認する:の&=代わりに使用しun1=ます。配列内のすべての値が等しい場合、ブロードキャストされた要素ごとの等価比較により、N x Nすべて1のマトリックスが生成されます。すべての値が等しくない場合、このマトリックスには0値が含まれるため、偽と見なされます。


4

暗黙的な入力

ほとんどの関数は、いくつかの入力を受け入れます。これらの入力は、スタックの最上部から取得されます。スタックの一番上に十分な引数が含まれていない場合、入力から残りの引数を描画します。(ドキュメントのセクション7.3を参照)元の説明を引用したい:

暗黙的な入力は次のように表示できます:スタックは、下から無限に拡張されます。つまり、位置0、-1、-2、...で、最初は定義されていない値ですが、暗黙的な入力によってオンザフライで解決されます。これらの入力は、必要な場合にのみ、必要な順序でユーザーに要求されます。複数の入力が同時に必要な場合、それらは通常のスタック順序に従います。つまり、(拡張)スタックの最も深い入力が最初に入力されます。


2
暗黙の入力は@flawrによって示唆された機能です
ルイスMendo

6
@flawrは本当に賢い人でなければなりません。:D
フレイ

3

多くの場合、論理配列は数値配列として使用できます

多くの場合TF、0と1の配列リテラルの代わりに「」表記を使用できます。例えば、FTF同じである[0,1,0]だけで、FTF生成logical値ではないdouble値。算術演算は論理値を数値として扱うため、これは通常問題になりません。たとえば、FTFQgives [1,2,1]Qは「1ずつ増加」)です。

場合によっては、数値のバイナリへの変換が短くなる場合があります。たとえば[1,0,1]TFT5Bは同じです。ここでも、最後の2つはlogical値であることに注意してください。


TF(論理)と[1 0](数値)の違いが重要な場合は、インデックスとして使用する場合です。logicalインデックスとして使用される型の配列はT、に対応する要素を選択し、に対応する要素を破棄しFます。したがって、[10 20]TF)プロデュース10(最初の要素を選択)、[10 20][1 0])プロデュース[10 20](インデックス[1 0]はの解釈を持ち1:endます。つまり、配列のすべての要素を選択します)。


3

サイズn-1のforループ

交換を検討

tnq:"...

td"...

1バイト以上まで保存します


@Luis true!ループされている元のベクトルが必要かもしれないと考えましたが、それは最初のアプローチでも不可能です。その発言を削除します。
-Sanchises

ただし、必ずしも1バイトを保存するとは限りません。あなたが必要とするかどうかに応じて1または2の保存@/ X@ループ内かどうか。たぶん「バイトを節約する」と言うことができます
ルイスメンドー

3

暗黙的な終了を活用するために、ループの後からループ内に物事を移動します

ループend文は、]、することができ取り残さそれらの後にはコードがない場合。これらは、MATLパーサーによって暗黙的に入力されます。

ループの後からループ内に物を移動できれば、最終を保存できます]

具体的な例として、次のコードは、数値の階乗に後続ゼロがいくつあるかを調べますNこちらを参照)。

  • コードはから1にループしNます。
  • それらの数値のそれぞれについて、その素因数を計算し、5存在する回数を決定します。
  • 答えは、5出現回数の累積です(これ5は、それぞれに少なくとも1つあるため機能します2)。

最初のアイデアは:"@Yf5=]vs(ループの後にステートメントがあることに注意してください):

:      % Range from 1 to implicit input
"      % For each number in that vector
  @    %   Push that number
  Yf   %   Vector of prime factors (with repetitions)
  5=   %   True for entries that equal `5`, and `false` for the rest
]      % End for
v      % Concatenate all vectors as a column vector
s      % Sum. Implicitly display

以来v、デフォルトでは、すべてのスタックの内容を連結し、それがループ内に移動させることができます。また、追加は連想的であるsため、移動することもできます。これ]はコードの最後にあるため、省略できます:"@Yf5=vs

:      % Range from 1 to implicit input
"      % For each number in that vector
  @    %   Push that number
  Yf   %   Vector of prime factors (with repetitions)
  5=   %   True for entries that equal `5`, and `false` for the rest
  v    % Concatenate all vectors so far as a column vector
  s    % Sum. Inplicitly end loop and display

私はこの象形文字に似た書き言葉のダイムを知らないが、多分次の3か月でそれを勉強する私の時間の大部分を留保します。
Abr001am

@ Agawa001 :-)これは、Matlabに非常に似ていることがわかります。ここで
ルイスメンドー

3

スタックが空の場合、空の数値配列を定義する簡単な方法

空の数値配列をプッシュするには、通常を使用します[]。ただし、スタックが空の場合、を使用してバイトを保存できますv。この関数はデフォルトですべてのスタックの内容を垂直に連結するため、スタックが空の場合は空の配列を生成します。

例えば、ここで実際にそれを見ることができます


2

一部の関数は、MATLABまたはOctaveと比較して拡張されています

MATLABまたはOctaveから来た場合、多くのMATL関数はこれらの言語の関数に似ていることがわかります。しかし、それらの多くでは機能が拡張されています。

例として、reshapeMATLのに対応するMATLABの関数を 考えeます。コードスニペットreshape([10 20 30 40 50 60], 2, 3)とは、reshape([10 20 30 40 50 60], 2, [])それぞれ「行ベクトル[10 20 30 40 50 60を2×3マトリックスに再形成する」、または「必要な数の列を持つ2行マトリックスに」を意味します。結果は、どちらの場合も2D配列です

10    30    50
20    40    60

以下のようなものreshape([10 20 30 40 50 60], 2, 2)か、reshape([10 20 30 40 50 60], 5, [])互換性がないためサイズの誤差を与えるだろう。ただし、MATLは最初の場合は要素を削除し(オンラインで試してください!)、2番目の場合は要素をゼロで埋めますオンラインで試してください!)ため、それぞれ、

10 30
20 40 

そして

10 60
20  0
30  0
40  0
50  0

MATLABの対応するものと比較して機能が拡張されている他の関数は、(非網羅的リスト)Ssort)、Ybstrsplit)、mismember)、hhorzcat)、vvertcat)、Zdgcd)、Zmlcm)、YScircshift)、YAdec2base)、ZAbase2dec)、Z"blanks)。


1

存在する場合、最初の非ゼロ要素のインデックスを取得します

このf関数は、配列のすべての非ゼロ要素のインデックスを提供します。多くの場合、最初の非ゼロ要素のインデックスが必要です。つまり、最初の要素をf1)適用fして選択します。ただし、元の配列にゼロ以外の値fが含まれていない場合、空の配列([])が出力され、最初の要素を選択しようとするとエラーが発生します。

一般的には、より堅牢な要件は、最初の要素のインデックスを得ることである少なくとも一つがある場合、および[]そうでありません。これは、のif後のブランチを使用して実行できますfが、バイトが高価です。より良い方法はfX<、つまり、最小関数X<をの出力に適用することですfX<入力が空の配列の場合、空の配列を返します。

オンラインでお試しください!(空の配列はまったく表示されないことに注意してください)。または、こちらの職場での例をご覧ください。


1

指定された配列の範囲を生成します

TL; WR:配列にゼロ以外の要素しかない場合のf代わりに使用しn:ます。


これは、1つのアレイを生成する必要があることが多い場合で指定された配列の要素数です。それを行う標準的な方法はです。たとえば、コードは数値ベクトルを入力として受け取り、各エントリにインデックスを乗算して計算します。[1 2 ... L]Ln:tn:*

指定された配列に非ゼロエントリのみが含まれること保証されている場合(たとえば、正の整数で構成されるか、印刷可能な文字を含む文字列である場合)、n:で置き換えることができfます。これにより、非ゼロエントリのインデックスを持つ配列が生成されます。したがって、上記のコードはになりtf*、1バイト節約されます。

いくつかのより複雑な例:123


1

数値配列リテラルを効率的に定義する

数値配列リテラルを定義するときにバイトを節約するために使用できるいくつかの方法を次に示します。それらを使用する回答例へのリンクがあります。これらは@Sueverによって作成された分析スクリプトを使用して取得されています

連結と事前定義されたリテラル

小さい番号の配列のためには、時々連結(関数を使用することができるhv比較:セパレータとしてスペースを使用しないように)、ならびに事前に定義されたリテラルを[2 4]2 4hそして2Kh、アレイを定義するすべてが[2 4]。同様に2K1v、空のスタックではを定義します[2; 4; 1]

数値配列リテラル内の文字

少し大きい数値の場合、一部の文字が配列リテラル内で数値の意味を持つという事実を利用して、スペースを節約できます。そのため、代わりに[3 5 2 7;-4 10 12 5]を使用できます[IAHC;dX12A]

具体的には、配列リテラル内で、

  • OlH I Kそれらの通常の意味を有します0、...、4
  • A、...、E平均5、...、9
  • X 手段 10
  • a、... d意味-1、...、-4
  • JそしてG平均1j-1j
  • P 手段 pi
  • Y 手段 inf
  • Nを意味しNaNます。

文字列と連続した違い

数値が大きい場合は、文字列を定義し、その連続した差を(でd)計算すると役立ちます。代わりに[20 10 35 -6]を使用できます'!5?b\'d。これdは、文字のコードポイントを使用して差異を計算するために機能します。

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