4つの整数を比較し、最大値に基づいて単語を返す


9

この関数は、4つの整数の入力を(取るべきabcd)との値は、4つの最大値に等しくれるバイナリワード基づくを返します。

戻り値は〜の間に1なり0xFます。

例えば:

a = 6, b = 77, c = 1, d = 4

戻り値2(バイナリ0010; 2番目の最下位ビットのみbが唯一の最大値であることに対応して設定されます)

a = 4, b = 5, c = 10, d = 10

戻り値0xC(バイナリ1100; 最大値に対応しcd最大値に等しい3番目と4番目の最下位ビットセット)

a = 1, b = 1, c = 1, d = 1

戻り値0xF(バイナリ1111;すべての値が最大値に等しいため4ビットすべてが設定されます)

ここに簡単な実装があります:

int getWord(int a, int b, int c, int d)
{
    int max = a;
    int word = 1;
    if (b > max)
    {
        max = b;
        word = 2;
    }
    else if (b == max)
    {
        word |= 2;
    }
    if (c > max)
    {
        max = c;
        word = 4;
    }
    else if (c == max)
    {
        word |= 4;
    }
    if (d > max)
    {
        word = 8;
    }
    else if (d == max)
    {
        word |= 8;
    }
    return word;
}

戻り値は0と1の文字列、ブール/ビットベクトル、または整数です。


2
私はゴルフ言語のソリューションを持っています。組み込みのリバース、マキシマム、等価チェック、結合、バイナリから整数への変換、整数から16進数への変換を使用しています。これは、等価チェックのためにスコアが1であることを意味しますか?私は...これはあまりにも正規言語に焦点を当て、さらにはそれが100%LETのためのスコアリングは、最大-組み込みを言うはっきりしていない人のためされて感じています。S
ケビンCruijssen

1
1.この質問をcode-golfに変更します。これはバイト数のみを考慮します。2.または、特定の言語に限定し(特定のバージョンのコンパイラ/インタープリタを使用してください)、許可されているすべてのステートメントと演算子、およびそれらのスコアリング方法をリストします。
-tsh

5
IMOの方が良いオプションです。これは完全に良いコードゴルフ問題になると思います。回答に使用できる言語を制限することから得られるメリットは何もありません
senox13

2
質問を更新して基準を削除しました。それがまだはっきりしないことを知らせてください
アンダーソン氏

5
10進数を出力する必要がありますか?または、代わりに4桁の2進数を出力できますか?
tsh

回答:




4

APL(Dyalog Unicode)、4 バイトSBCS

匿名の暗黙のプレフィックス関数。取り[a,b,c,d]引数として。ビットブール配列を返します。*

⌈/=⌽

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

⌈/ 引数の最大値を行います

= 等しい(ベクトル化)

 議論の逆?

* APLは、値ごとに1ビットを使用してブール値の配列を格納するため、表示形式にかかわらず、これは実際に4ビットワードを返し0 0 1 0ます。



2

Perl 6、12バイト

{$_ X==.max}

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

整数のリストを取り、ブール値のリストを返す匿名コードブロック。数値として返す必要がある場合、コードブロックの内側をでラップするのは+4バイト2:[...]です。

説明:

{          }  # Anonymous code block
 $_           # With the input
    X==       # Which values are equal
       .max   # To the maximum element

OPは、ラップする必要がないと表示します。
アダム

2

Japt、5

m¶Urw

それを試してみてください!

@Oliverのおかげで-4バイト!
@Shaggyのおかげで-2バイト!

入力は、次の形式の4要素配列です。

[d, c, b, a]

出力はビットの配列です。


もちろんあります;)明らかに学ぶべき多くの近道があります。
dana

ブール配列が許容可能な出力である場合、これは7バイトになる可能性があります
Oliver

@ Oliver、5バイト ;)
Shaggy

あなたたちはかなり良いです:)それはrw変換がr("w")繰り返し最大値を取得することによって還元を行う方法が面白いです。に変換する場合も同様U.m("===", ...)です。いずれにせよ、ヒントをありがとう!
dana

2

x86マシンコード(MMX / SSE1)、26バイト(4x int16_t)

x86マシンコード(SSE4.1)、28バイト(4x int32_tまたはuint32_t)

x86マシンコード(SSE2)、24バイト(4x float32)または27Bからctt int32

(int32をfloatに変換する最後のバージョンは、同じfloatに丸める大きな整数に対して完全に正確ではありません。float入力では、丸めは呼び出し元の問題であり、NaNがない場合、この関数は正しく機能し、比較するfloatを識別します==整数バージョンはすべての入力に対して機能し、符号付き2の補数として扱います。)

これらはすべて、同じマシンコードで16/32/64ビットモードで動作します。

stack-args呼び出し規約は、argsを2回ループすることを可能にし(maxを検索してから比較する)、おそらくより小さな実装になりますが、私はそのアプローチを試していません。

x86 SIMDは単一の命令(pmovmskbor movmskpsまたはpd)としてvector-> integerビットマップを持っているため、MMX / SSE命令が少なくとも3バイトの長さであっても、これは当然のことでした。SSSE3以降の命令はSSE2よりも長く、MMX / SSE1命令は最短です。pmax*(packed-integer vertical max)の異なるバージョンが異なるタイミングで導入され、SSE1(mmx regの場合)とSSE2(xmm regの場合)には符号付きワード(16ビット)と符号なしバイトしかありませんでした。

pshufwおよびpmaxswMMXレジスタはKatmai Pentium IIIで新しく追加されたため、実際にはMMX CPU機能ビットだけでなく、SSE1が必要です。)

これはunsigned max4_mmx(__m64)__m64引数をに渡すi386 System V ABIと同様に、Cから呼び出すことができmm0ます。(渡さないのx86-64システムV、__m64xmm0!)

   line         code bytes
    num  addr   
     1                         global max4_mmx
     2                             ;; Input 4x int16_t in mm0
     3                             ;; output: bitmap in EAX
     4                             ;; clobbers: mm1, mm2
     5                         max4_mmx:
     6 00000000 0F70C8B1           pshufw    mm1, mm0, 0b10110001   ; swap adjacent pairs
     7 00000004 0FEEC8             pmaxsw    mm1, mm0
     8                         
     9 00000007 0F70D14E           pshufw    mm2, mm1, 0b01001110   ; swap high/low halves
    10 0000000B 0FEECA             pmaxsw    mm1, mm2
    11                         
    12 0000000E 0F75C8             pcmpeqw   mm1, mm0               ; 0 / -1
    13 00000011 0F63C9             packsswb  mm1, mm1               ; squish word elements to bytes, preserving sign bit
    14                         
    15 00000014 0FD7C1             pmovmskb  eax, mm1          ; extract the high bit of each byte
    16 00000017 240F               and       al, 0x0F          ; zero out the 2nd copy of the bitmap in the high nibble
    17 00000019 C3                 ret

size = 0x1A = 26 bytes

があった場合pmovmskwpacksswband(3 + 2バイト)を節約したはずです。MMXレジスタではすでに上位バイトがゼロであるand eax, 0x0fためpmovmskb、必要ありません。MMXレジスターは8バイト幅しかないので、8ビットALはすべての可能な非ゼロビットをカバーします。

入力が負でないことがわかっている場合packsswb mm1, mm0、の上位4バイトに負でない符号付きバイトを生成し、after mm1の必要性を回避できます。 したがって、24バイトです。andpmovmskb

符号付き飽和を備えたx86パックは、入力と出力を符号付きとして処理するため、常に符号ビットを保持します。(https://www.felixcloutier.com/x86/packsswb:packssdw)。おもしろい事実:符号なし飽和のx86パックでも、入力は符号付きとして扱われます。これがPACKUSDWSSE4.1まで導入されなかった理由かもしれませんが、MMX / SSE2以降、サイズと署名のその他の3つの組み合わせが存在していました。


または、XMMレジスタに(およびのpshufd代わりにpshufw)32ビット整数を使用するとmovmskps、pack / and を置き換えることを除いて、すべての命令にプレフィックスバイトがさらに1つ必要になります。しかしpmaxsd/ pmaxud追加の追加バイトが必要です...

Cからコールunsigned max4_sse4(__m128i);するx86-64システムV、またはMSVCのvectorcall(と-Gv通過両方とも)、__m128i/ __m128d/ __m128XMMのREGSで引数が始まりますxmm0

    20                         global max4_sse4
    21                             ;; Input 4x int32_t in xmm0
    22                             ;; output: bitmap in EAX
    23                             ;; clobbers: xmm1, xmm2
    24                         max4_sse4:
    25 00000020 660F70C8B1         pshufd    xmm1, xmm0, 0b10110001   ; swap adjacent pairs
    26 00000025 660F383DC8         pmaxsd    xmm1, xmm0
    27                         
    28 0000002A 660F70D14E         pshufd    xmm2, xmm1, 0b01001110   ; swap high/low halves
    29 0000002F 660F383DCA         pmaxsd    xmm1, xmm2
    30                         
    31 00000034 660F76C8           pcmpeqd   xmm1, xmm0               ; 0 / -1
    32                         
    33 00000038 0F50C1             movmskps  eax, xmm1          ; extract the high bit of each dword
    34 0000003B C3                 ret

size = 0x3C - 0x20 = 28 bytes

または、入力をとして受け入れる場合float、SSE1命令を使用できます。floatフォーマットは、整数値の広い範囲を表すことができ...

または、ルールを曲げすぎていると思われる場合は0F 5B C0 cvtdq2ps xmm0, xmm0、変換する3バイトから始めて、IEEEバイナリ32として正確に表現できるすべての整数に対して機能する27バイトの関数を作成しfloat、一部の入力が取得される入力の多くの組み合わせ変換中に2、4、8などの倍数に丸められます。(つまり、SSE4.1バージョンよりも1バイト小さく、SSE2のみを備えたすべてのx86-64で動作します。)

フロート入力のいずれかがNaNで、ノートの場合はmaxps a,b正確に実装し(a<b) ? a : b順不同で第二オペランドからの要素を保ちます。そのため、入力にNaNが含まれている場合でも、それらがどこにあるかによって、これがゼロ以外のビットマップで返される可能性があります。

unsigned max4_sse2(__m128);

    37                         global max4_sse2
    38                             ;; Input 4x float32 in xmm0
    39                             ;; output: bitmap in EAX
    40                             ;; clobbers: xmm1, xmm2
    41                         max4_sse2:
    42                         ;    cvtdq2ps  xmm0, xmm0
    43 00000040 660F70C8B1         pshufd    xmm1, xmm0, 0b10110001   ; swap adjacent pairs
    44 00000045 0F5FC8             maxps     xmm1, xmm0
    45                         
    46 00000048 660F70D14E         pshufd    xmm2, xmm1, 0b01001110   ; swap high/low halves
    47 0000004D 0F5FCA             maxps     xmm1, xmm2
    48                         
    49 00000050 0FC2C800           cmpeqps   xmm1, xmm0               ; 0 / -1
    50                         
    51 00000054 0F50C1             movmskps  eax, xmm1          ; extract the high bit of each dword
    52 00000057 C3                 ret

size = 0x58 - 0x40 = 24 bytes

のコピーアンドシャッフルpshufdは、私たちの最善の策です:fromのshufps dst,src,imm8下半分の入力を読み取ります。また、非破壊的なコピーとシャッフルの両方が必要なため、3バイトと/ pdは両方とも使用できません。スカラーの最大値に絞り込んでいる場合、それらを使用できますが、すべての要素に最大値がまだない場合、比較する前にブロードキャストするために別の指示が必要です。dst dstmovhlpsunpckhps


関連:SSE4.1 phminposuwuint16_t、XMMレジスターで最小値の位置と値を見つけることができます。65535から減算して最大値に使用するのは良いことではないと思いますが、最大バイト数または符号付き整数に使用することに関するSOの回答を参照してください。


1

Python 3.8(プレリリース)、67バイト

4つの整数を取り、Python 3.8の新しい代入演算子の助けを借りて、比較のブール結果を最大値にビットシフトし、結果のビットごとのORを返すLambda関数

lambda a,b,c,d:((m:=max(a,b,c,d))==d)<<3|(m==c)<<2|(m==b)<<2|(a==m)

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


:=は、ロータスノーツの数式の代入演算子であった昔のことを思い出させます。私は昔のために3.8を見なければならないだろうと思います:)
ElPedro


1

05AB1E3 2 バイト

ZQ

のリストとして入力し、[d,c,b,a]ブール値のリストとして出力します。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

Z    # Take the maximum of the implicit input-list
 Q   # Check for each in the (implicit) input-list if it equals this value
     # (and output implicitly as result)

OPが更新されました。16進数に変換する必要はありません。
アダム



1

Pythonの359バイト 66バイト

def f(l):
 n=max(a)
 for i in 0,1,2,3:a[i]=a[i]==n
 return a[::-1]

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

入力を取り[a,b,c,d]、ブール値のリストを出力します。

適切な関数になるように編集し、条件を囲む括弧を削除して2バイト節約しました。


1
こんにちは、PPCGへようこそ。現状では、回答はスニペットの形式になっていますが、許可されていません。I / Oコンセンサスに準拠するように回答を修正してください。つまり、機能または完全なプログラムにします。
Jonathan Frech

1
編集。初めて。頭を高く評価してください!
Bsoned

ラムダ内でこのリスト内包を使用して、37バイトに減らすことができます。PPCGへようこそ。ご滞在をお楽しみください。
Value Ink

@ValueInk余分な空白を削除すると、さらに1バイト節約されます。
Jonathan Frech

1

1. Python 3.5、90バイト

数値のシーケンスをパラメーターとして受け取ります。「バイナリ」文字列を返します

import sys;v=[*map(int,sys.argv[1:])];m=max(v);s=""
for e in v:s=str(int(e==m))+s
print(s)

例:

$ ./script.py 6 77 1 4 77
10010

説明

import sys
# convert list of string parameters to list of integers
v=[*map(int,sys.argv[1:])]
# get max
m=max(v)
# init outstring
s=""
# walk through list
for e in v:
    # prepend to outstring: int(True)=>1, int(False)=>0
    s=str(int(e==m))+s
# print out result
print(s)

1

C#(Visual C#Interactive Compiler)、26バイト

n=>n.Select(a=>a==n.Max())

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

形式で入力を受け取ります[d,c,b,a]。以下の他のすべては、[a,b,c,d]

C#(Visual C#Interactive Compiler)、35バイト

n=>n.Select((a,b)=>n[3-b]==n.Max())

を返しますIEnumerable<bool>

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

C#(Visual C#Interactive Compiler)、39バイト

n=>n.Select((a,b)=>n[3-b]==n.Max()?1:0)

IEnumerable<int>ビットを表すを返します。

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

C#(Visual C#Interactive Compiler)、49バイト

n=>{for(int i=4;i-->0;Write(n[i]==n.Max()?1:0));}

バイナリ文字列をSTDOUTに出力します。

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


IEnumerable<bool> ある許容できます。
アダム


0

これはバイナリとして出力するJSバージョンです

更新:結合あり、ルックアップなしの方が短い:

JavaScript(Node.js)、42バイト

a=>a.map(x=>+(x==Math.max(...a))).join('')

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

以前、ルックアップあり、49バイト

a=>a.map(x=>[0,1][+(x==Math.max(...a))]).join('')

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

以前、reduceを使用して、52バイト:

a=>a.reduce((y,x)=>y+[0,1][+(x==Math.max(...a))],'')

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

fa=>a.map(x=>+(x==Math.max(...a))).join('')
console.log(f([ 4, 1,77, 6])) // 0010
console.log(f([10,10, 5, 4])) // 1100
console.log(f([ 1, 1, 1, 1])) // 1111


1
[0,1][...]01

@Arnauldは今や明らかなようです。ありがとう!
Pureferret

0

C#(Visual C#Interactive Compiler)、51バイト

x=>{for(int m=x.Max(),i=4;i-->0;)x[i]=x[i]==m?1:0;}

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

上記は、引数を変更し出力する無名関数です。出力は1と0の配列です。

以下は、整数を出力する再帰関数です。

C#(Visual C#Interactive Compiler)、60バイト

int f(int[]x,int i=3)=>i<0?0:2*f(x,i-1)|(x[i]==x.Max()?1:0);

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

どちらの関数も、入力を4要素の配列として受け取ります。

[d, c, b, a]

整数を出力する必要はありません。
アダム

@アダム-ありがとう:)私が他の答えに取り組んでいる間に投稿した後、これに気付きました。変更する前に、多くの優れたトリックを使用する別のC#回答がありました。
ダナ



0

バッチ、92バイト

@set m=%1
@set f=@for %%i in (%*)do @
%f%set/a"m=m+(m-=%%i)*(m>>31)
%f%cmd/cset/a!(m-%%i)

引数をコマンドラインパラメータとして逆の順序で受け取ります。パラメータの最大値を減らし、現在の最大値との正の差のみを追加することにより、パラメータの最大値を算術的に計算し、次に各パラメータを再度マッピングして、最大値と比較します。便宜上cmd/cset/a、改行を出力しないため、結果は自動的に連結されます。%f%単に繰り返される構造であるものに5つのバイトを保存します。

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