4 개의 정수를 비교하고 최대 값을 기준으로 단어를 반환


9

이 함수는 네 개의 정수 입력을 (한다 a, b, c, d되는 값은 최대 네 개의 동일 기반 이진 워드)를 반환.

반환 값은 사이가 될 것입니다 10xF.

예를 들면 다음과 같습니다.

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

반환 2(이진 0010, b유일한 최대 값에 해당하는 2 번째 최하위 비트 만 설정 됨 )

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

반환 0xC(바이너리 1100, 3 차 및 제 4 최하위 비트에 대응하는 세트 cd최대 값과 동등)

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 % 명확하지 않다고 생각합니다. : :
Kevin Cruijssen

1
1.이 질문을 code-golf로 변경하면 바이트 수에만 관심이 있습니다. 또는 특정 언어 (구체적인 컴파일러 / 인터프리터 버전)로 제한하고 허용되는 모든 문장과 연산자 및 점수를 매기는 방법을 나열합니다.
tsh

5
1이 더 나은 옵션 인 IMO입니다. 나는 이것이 코드 골프 문제를 완벽하게 해결한다고 생각하며 답을 구할 수있는 언어를 제한함으로써 얻을 수있는 이점을 볼 수 없다
senox13

2
기준을 제거하기 위해 질문을 업데이트했습니다. 그것이 여전히 불분명하다는 것을 알려주세요
Mr Anderson Anderson

5
십진수를 출력해야합니까? 아니면 대신 4 개의 이진수를 출력 할 수 있습니까?
tsh

답변:




4

APL (Dyalog Unicode) , 4 바이트 SBCS

익명의 암묵적 접두사 기능. 소요 [a,b,c,d]인수로. 비트 부울 배열을 반환합니다. *

⌈/=⌽

온라인으로 사용해보십시오!

⌈/ 인수의 최대를한다

= 같음 (벡터화)

 논쟁의 반대?

* APL은 값당 1 비트를 사용하여 부울 배열을 저장하므로 표시 형식은에도 불구하고 실제로 4 비트 워드를 반환합니다 0 0 1 0.



2

펄 6 , 12 바이트

{$_ X==.max}

온라인으로 사용해보십시오!

정수 목록을 가져 와서 부울 목록을 리턴하는 익명 코드 블록. 숫자로 반환 해야하는 경우 코드 블록 내부를로 감싸는 것이 +4 바이트입니다 2:[...].

설명:

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

OP는 이제 포장 할 필요가 없다고 말합니다.
Adám

2

apt, 5

m¶Urw

시도 해봐!

@Oliver 덕분에 -4 바이트!
@Shaggy 덕분에 -2 바이트!

입력은 다음 형식의 4 요소 배열입니다.

[d, c, b, a]

출력은 비트 배열입니다.


물론;)가 있습니다. 배울 수있는 지름길이 많이 있습니다.
dana

부울 배열이 허용되는 출력이면 7 바이트 일 수 있습니다.
Oliver

@Oliver, 5 bytes ;)
얽히고 설킨

당신은 꽤 좋습니다 :) 반복적으로 최대 값을 얻어서 감소 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-cvt int32

int32를 float로 변환하는 마지막 버전은 동일한 float로 반올림하는 큰 정수에 대해서는 완벽하게 정확하지 않습니다. float 입력의 경우 반올림은 호출자의 문제이며 NaN이 없으면이 함수는 올바르게 작동하여 ==를 비교하는 float을 식별합니다. 정수 버전은 모든 입력에 대해 작동하며 부호있는 2의 보수로 처리합니다.)

이들 모두는 동일한 머신 코드를 사용하여 16/32/64 비트 모드에서 작동합니다.

스택 인수 호출 규칙을 사용하면 args를 두 번 반복 (최대 값 찾기 및 비교) 할 수 있으므로 더 작은 구현을 제공 할 수는 있지만 그 방법을 시도하지는 않았습니다.

x86 SIMD에는 벡터-> 정수 비트 맵이 단일 명령어 ( pmovmskb또는 movmskpspd)로 포함되어 있으므로 MMX / SSE 명령어의 길이가 3 바이트 이상이지만 자연 스럽습니다. SSSE3 이상 명령어는 SSE2보다 길며 MMX / SSE1 명령어가 가장 짧습니다. pmax*부호있는 단어 (16 비트) 및 부호없는 바이트 만 갖는 SSE1 (mmx regs) 및 SSE2 (xmm regs)와 함께 다른 버전의 (packed-integer vertical max)가 다른 시간에 도입되었습니다.

( pshufwpmaxswMMX에 등록 그래서 정말 그들이 SSE1뿐 아니라 MMX CPU 기능 비트를 필요 케트 마이 펜티엄 III와 새로운입니다.)

이는 i에서 arg unsigned max4_mmx(__m64)를 전달하는 i386 System V ABI와 마찬가지로 C에서 호출 할 수 있습니다 . (전달되지 않음 - 64 시스템 V, 에 !)__m64mm0__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

이 있었다면 pmovmskw어떤 일이 저장된 것 packsswband(3 + 2 바이트). MMX 레지스터에서 이미 상위 바이트를 0으로 만들기 and eax, 0x0f때문에 필요하지 않습니다 pmovmskb. MMX 레지스터는 폭이 8 바이트에 불과하므로 8 비트 AL은 0이 아닌 모든 비트를 포함합니다.

입력이 음수가 아닌 것을 알고 있다면packsswb mm1, mm0 의 상위 4 바이트에서 음이 아닌 부호있는 바이트를 생성 할 수mm1 있으므로 andafter 의 필요성을 피할 수 pmovmskb있습니다. 따라서 24 바이트입니다.

부호있는 채도를 가진 x86 팩은 입력 및 출력을 부호있는 것으로 취급하므로 항상 부호 비트를 유지합니다. ( https://www.felixcloutier.com/x86/packsswb:packssdw ). 재미있는 사실 : 서명되지 않은 채도를 가진 x86 팩은 여전히 입력 을 서명 된 것으로 취급합니다 . 이것이 PACKUSDWSSE4.1까지 소개되지 않은 이유 일 수 있지만 MMX / SSE2 이후로 크기와 서명의 다른 3 가지 조합이 존재했습니다.


또는 XMM 레지스터 (및 pshufd대신 pshufw) 에 32 비트 정수를 사용 movmskps하면 팩 / 및 교체를 제외하고 모든 명령에 접두어 바이트가 하나 더 필요합니다 . 그러나 pmaxsd/ pmaxud여분의 여분의 바이트가 필요합니다 ...

같은 C에서 호출unsigned max4_sse4(__m128i); - 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 binary32로 정확하게 표현할 수있는 모든 정수 float와 일부 입력이있는 여러 입력 조합에서 작동하는 27 바이트 함수를 작성 하십시오 변환하는 동안 2, 4, 8의 배수로 올림합니다. (따라서 SSE4.1 버전보다 1 바이트 작으며 SSE2 만있는 모든 x86-64에서 작동합니다.)

플로트 입력 중 하나가 NaN의 메모를하는 경우가 maxps a,b정확하게 구현 (a<b) ? a : b, 정렬되지 않은에서 두번째 피연산자에서 요소를 유지 . 따라서 입력 위치에 따라 일부 NaN이 입력에 포함되어 있어도 0이 아닌 비트 맵으로 반환 될 수 있습니다.

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은 여전히 ​​최선의 방법 입니다 . 에서의shufps dst,src,imm8 절반에 대한 입력을 읽습니다 . 또한 비파괴 복사 및 셔플이 두 번 필요하므로 3 바이트 와 / pd가 모두 나옵니다. 스칼라 최대 값으로 좁히는 경우이를 사용할 수 있지만 모든 요소에 최대 값이없는 경우 비교하기 전에 브로드 캐스트하는 데 다른 명령이 필요합니다.dst dstmovhlpsunpckhps


관련 : SSE4.1 phminposuwuint16_tXMM 레지스터에서 최소값의 위치와 값을 찾을 수 있습니다 . 최대로 사용하기 위해 65535에서 빼는 것이 승리라고 생각하지 않지만 최대 바이트 또는 부호있는 정수 에 사용하는 것에 대한 SO 답변을 참조하십시오 .


1

Python 3.8 (시험판) , 67 바이트

4 개의 정수를 취하고, 파이썬 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)

온라인으로 사용해보십시오!


: = Lotus Notes 수식을 사용하는 할당 연산자였던 옛날을 생각 나게합니다. 옛날 술을 위해 3.8을 살펴 봐야 할 것
같아요





1

파이썬 3 , 59 바이트 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 불필요한 공백을 제거하면 또 다른 바이트가 절약됩니다.
Jonathan Frech

1

1. 파이썬 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 # 대화식 컴파일러) , 39 바이트

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

IEnumerable<int>비트를 나타내는를 반환합니다 .

온라인으로 사용해보십시오!

C # (Visual C # 대화식 컴파일러) , 49 바이트

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

이진 문자열을 STDOUT에 인쇄합니다.

온라인으로 사용해보십시오!


IEnumerable<bool> 으로 허용.
Adám

0

PHP, 54 바이트

while($i<4)$argv[++$i]<max($argv)||$r+=1<<$i-1;echo$r;

또는

while($i<4)$argv[++$i]<max($argv)||$r+=1<<$i;echo$r/2;

명령 행 인수에서 입력을 가져옵니다. 온라인으로 실행 -nr하거나 사용해보십시오 .


0

바이너리로 출력되는 JS 버전이 있습니다.

업데이트 : 조인 및 조회가없는 짧은 :

자바 스크립트 (Node.js) , 42 바이트

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

온라인으로 사용해보십시오!

이전, 조회, 49 바이트

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

온라인으로 사용해보십시오!

이전에는 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][...]이미 하나의 색인을 사용하고 있으므로 안전하게 제거 할 수 있습니다0 또는 1.
Arnauld

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

정수를 출력 할 필요가 없습니다.
Adám

@Adam-thanks :) 다른 답변을 작성하는 동안 게시 한 후에 이것을 깨달았습니다. 변경하기 전에 좋은 속임수를 많이 사용하는 또 다른 C # 답변이있었습니다.
dana



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.