Comparez quatre entiers, renvoyez le mot en fonction du maximum


9

Cette fonction devrait prendre quatre entrées de nombres entiers ( a, b, c, d) et retourner un mot binaire sur la base duquel les valeurs sont égales au maximum de quatre.

La valeur de retour sera comprise entre 1et 0xF.

Par exemple:

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

renvoie 2(binaire 0010; seul le deuxième bit de poids faible est défini, ce qui correspond à la bseule valeur maximale)

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

renvoie 0xC(binaire 1100; 3e et 4e bits de poids faible définis correspondant à cet dégalant la valeur max)

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

renvoie 0xF(binaire 1111; les quatre bits sont définis car toutes les valeurs sont égales au maximum)

Voici une implémentation simple:

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

la valeur de retour peut être une chaîne de 0 et de 1, un vecteur bool / bit ou un entier


2
J'ai une solution dans un langage de golf, qui utilise les fonctions inversées, maximales, de vérification d'égalité, de jointure, de conversion de binaire en entier, de entier en hexadécimal. Est-ce à dire que mon score est de 1 en raison du contrôle d'égalité? J'ai le sentiment que cela est trop axé sur les langues régulières, et même pour ceux qui ne savent pas à 100% ce que le score pour disons un maximum intégré: S
Kevin Cruijssen

1
Je vous suggère d'essayer de: 1. changer cette question en code-golf, qui ne se soucie que du nombre d'octets. 2. ou, limitez-vous à une certaine langue (certaine version du compilateur / interprète s'il vous plaît), et listez toutes les instructions et opérateurs autorisés, et comment les noter.
tsh

5
1 est une meilleure option, OMI. Je pense que cela fait une très bonne question de code-golf et je ne vois aucun avantage à restreindre les langues disponibles pour les réponses
senox13

2
J'ai mis à jour ma question pour supprimer les critères. Faites-moi savoir que ce n'est toujours pas clair
M. Anderson

5
Dois-je sortir un nombre décimal? Ou puis-je produire 4 chiffres binaires à la place?
tsh

Réponses:


8

Gelée , 2 octets

Prend l'entrée comme [d,c,b,a]. Renvoie une liste de booléens.

Ṁ=

Essayez-le en ligne!

M aximum

= égal à (implique que l'autre argument est l'argument d'origine; vectorise)


5

R , 17 octets

max(a<-scan())==a

Essayez-le en ligne!

Renvoie un vecteur de booléens. Comme cette sortie a été confirmée, c'est préférable à la sortie numérique, car celle-ci est presque deux fois plus longue:

R , 33 octets

sum(2^which(max(a<-scan())==a)/2)

Essayez-le en ligne!


4

APL (Dyalog Unicode) , 4 octets SBCS

Fonction de préfixe tacite anonyme. Prend [a,b,c,d]comme argument. Renvoie un tableau bit-booléen. *

⌈/=⌽

Essayez-le en ligne!

⌈/ Est-ce que le maximum de l'argument

= égal (vectorise)

 l'inverse de l'argument?

* Notez qu'APL stocke des tableaux de booléens en utilisant un bit par valeur, donc cela retourne en effet un mot de 4 bits, malgré la forme d'affichage 0 0 1 0.



2

Perl 6 , 12 octets

{$_ X==.max}

Essayez-le en ligne!

Bloc de code anonyme qui prend une liste d'entiers et renvoie une liste de booléens. Si nous devons renvoyer un nombre, c'est +4 octets pour envelopper l'intérieur du bloc de code avec 2:[...].

Explication:

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

OP dit maintenant que vous n'avez pas besoin de terminer.
Adám

2

Japt, 5

m¶Urw

Essayez!

-4 octets grâce à @Oliver!
-2 octets grâce à @Shaggy!

L'entrée est un tableau à 4 éléments au format suivant:

[d, c, b, a]

La sortie est un tableau de bits.


Bien sûr qu'il y a;) Il y a apparemment beaucoup de raccourcis à apprendre.
dana

Si un tableau booléen est une sortie acceptable, cela peut être de 7 octets
Oliver

@Oliver, 5 octets ;)
Shaggy

Vous êtes assez bons :) C'est intéressant de voir comment la rwconversion en r("w")réduit en obtenant à plusieurs reprises le maximum. Même chose pour se convertir U.m("===", ...). Dans tous les cas, merci pour les conseils!
dana

2

Code machine x86 (MMX / SSE1), 26 octets (4x int16_t)

code machine x86 (SSE4.1), 28 octets (4x int32_t ou uint32_t)

code machine x86 (SSE2), 24 octets (4x float32) ou 27B vers cvt int32

(La dernière version qui convertit int32 en float n'est pas parfaitement précise pour les grands entiers qui arrondissent au même float. Avec l'entrée float, l'arrondi est le problème de l'appelant et cette fonction fonctionne correctement s'il n'y a pas de NaN, identifiant les flotteurs qui comparent == au maximum. Les versions entières fonctionnent pour toutes les entrées, les traitant comme des compléments signés 2.)

Tous ces éléments fonctionnent en mode 16/32/64 bits avec le même code machine.

Une convention d'appel stack-args permettrait de faire une boucle sur les arguments deux fois (trouver max puis comparer), ce qui pourrait nous donner une implémentation plus petite, mais je n'ai pas essayé cette approche.

x86 SIMD a vector-> bitmap entier comme une seule instruction ( pmovmskbou movmskpsou pd), il était donc naturel pour cela même si les instructions MMX / SSE sont longues d'au moins 3 octets. Les instructions SSSE3 et ultérieures sont plus longues que SSE2 et les instructions MMX / SSE1 sont les plus courtes. Différentes versions de pmax*(vertical à nombres entiers compressés max) ont été introduites à des moments différents, SSE1 (pour les registres mmx) et SSE2 (pour les registres xmm) ayant uniquement un mot signé (16 bits) et un octet non signé.

( pshufwet pmaxswsur les registres MMX sont nouveaux avec Katmai Pentium III, donc ils nécessitent vraiment SSE1, pas seulement le bit de fonctionnalité CPU MMX.)

Cela peut être appelé à partir de C comme unsigned max4_mmx(__m64)avec l'i386 System V ABI, qui transmet un __m64argument mm0. (Non x86-64 System V, qui passe __m64en xmm0!)

   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

S'il y avait un pmovmskw, ce qui aurait sauvé le packsswbet le and(3 + 2 octets). Nous n'en avons pas besoin and eax, 0x0fcar pmovmskbsur un registre MMX, les zéros supérieurs sont déjà zéros. Les registres MMX ne font que 8 octets de large, donc l'AL 8 bits couvre tous les bits non nuls possibles.

Si nous savions que nos entrées n'étaient pas négatives, nous pourrionspacksswb mm1, mm0 produire des octets signés non négatifs dans les 4 octets supérieurs de mm1, en évitant le besoin d' andafter pmovmskb. Donc 24 octets.

Le pack x86 avec saturation signée traite l'entrée et la sortie comme signées, donc il préserve toujours le bit de signe. ( https://www.felixcloutier.com/x86/packsswb:packssdw ). Fait amusant: le pack x86 avec saturation non signée traite toujours l' entrée comme signée. Cela pourrait être la raison pour laquelle il PACKUSDWn'a pas été introduit avant SSE4.1, alors que les 3 autres combinaisons de taille et de signature existaient depuis MMX / SSE2.


Ou avec des entiers 32 bits dans un registre XMM (et pshufdau lieu de pshufw), chaque instruction aurait besoin d'un octet de préfixe de plus, sauf pour movmskpsremplacer le pack / et. Mais pmaxsd/ pmaxudbesoin d'un octet supplémentaire ...

appelable à partir de C commeunsigned max4_sse4(__m128i); avec x86-64 System V, ou MSVC vectorcall ( -Gv), qui passent __m128i/ __m128d/ __m128args dans les regs XMM commençant par 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

Ou si nous acceptons la saisie en tant que float, nous pouvons utiliser les instructions SSE1. Le floatformat peut représenter une large gamme de valeurs entières ...

Ou si vous pensez que cela déforme trop les règles, commencez par un octet 0F 5B C0 cvtdq2ps xmm0, xmm0à convertir, créant une fonction de 27 octets qui fonctionne pour tous les entiers qui sont exactement représentables en tant que binaire IEEE32 float, et de nombreuses combinaisons d'entrées où certaines entrées obtiennent arrondi à un multiple de 2, 4, 8 ou autre lors de la conversion. (Il est donc 1 octet plus petit que la version SSE4.1 et fonctionne sur n'importe quel x86-64 avec seulement SSE2.)

Si l'une des entrées flottantes est NaN, notez qu'elle maxps a,bimplémente exactement (a<b) ? a : b, en gardant l'élément du 2e opérande non ordonné . Il pourrait donc être possible pour cela de retourner avec un bitmap non nul même si l'entrée contient du NaN, selon l'endroit où ils se trouvent.

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

copier-mélanger avec pshufdest toujours notre meilleur pari: shufps dst,src,imm8lit l'entrée pour la moitié inférieure dst de dst . Et nous avons besoin d'un copier-shuffle non destructif les deux fois, donc 3 octets movhlpset unpckhps/ pd sont tous les deux sortis. Si nous nous limitions à un maximum scalaire, nous pourrions les utiliser, mais cela coûte une autre instruction de diffuser avant de comparer si nous n'avons pas déjà le maximum dans tous les éléments.


Connexes: SSE4.1 phminposuwpeut trouver la position et la valeur du minimum uint16_tdans un registre XMM. Je ne pense pas que ce soit une victoire de soustraire de 65535 pour l'utiliser pour max, mais voir une réponse SO sur son utilisation pour max d'octets ou d'entiers signés.


1

Python 3.8 (version préliminaire) , 67 octets

Fonction lambda qui prend en 4 entiers, bit décale le résultat booléen de leur comparaison à la valeur maximale avec l'aide du nouvel opérateur d'affectation de Python 3.8 , et retourne le OU binaire des résultats

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

Essayez-le en ligne!


: = me rappelle les anciens jours où c'était l'opérateur d'affectation avec la formule Lotus Notes. Je suppose que je vais devoir jeter un œil à la version 3.8 pour le bon vieux temps :)
ElPedro



1

JavaScript (ES6), 30 octets

Prend l'entrée comme ([d,c,b,a]). Renvoie 4 valeurs booléennes.

a=>a.map(x=>x==Math.max(...a))

Essayez-le en ligne!


1
OP a précisé que vous pouvez en effet renvoyer 4 valeurs booléennes.
Adám


1

Python 3 , 59 octets 66 octets

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

Essayez-le en ligne!

Prend l'entrée en tant que [a,b,c,d]et génère une liste de booléens.

Modifié pour être une fonction appropriée, puis enregistré 2 octets en supprimant les crochets autour du conditionnel.


1
Bonjour et bienvenue chez PPCG. En l'état, votre réponse a la forme d'un extrait de code, qui n'est pas autorisé. Veuillez corriger votre réponse pour qu'elle soit conforme à notre consensus d'E / S , c'est-à-dire en faire une fonction ou un programme complet.
Jonathan Frech

1
Édité. Première fois. Appréciez la tête haute!
Bsoned

Vous pouvez le réduire à 37 octets en utilisant cette compréhension de liste dans un lambda. Bienvenue à PPCG et profitez de votre séjour!
Value Ink

@ValueInk La suppression du blanc superflu permet d'économiser encore un autre octet.
Jonathan Frech

1

1. Python 3.5, 90 octets

Prend une séquence de nombres comme paramètres. Renvoie une chaîne "binaire"

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

exemple:

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

Explication

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 octets

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

Essayez-le en ligne!

Prend l'entrée au format [d,c,b,a]. Tous les autres ci-dessous prennent en compte[a,b,c,d]

C # (Visual C # Interactive Compiler) , 35 octets

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

Renvoie un IEnumerable<bool>.

Essayez-le en ligne!

C # (Visual C # Interactive Compiler) , 39 octets

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

Renvoie un IEnumerable<int>, qui représente des bits.

Essayez-le en ligne!

C # (Visual C # Interactive Compiler) , 49 octets

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

Imprime une chaîne binaire dans STDOUT.

Essayez-le en ligne!


IEnumerable<bool> est acceptable.
Adám

0

PHP, 54 octets

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

ou

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

prendre l'entrée des arguments de ligne de commande. Courez avec -nrou essayez-les en ligne .


0

Voici une version JS qui sort en binaire

mise à jour: plus courte avec jointure et sans recherche:

JavaScript (Node.js) , 42 octets

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

Essayez-le en ligne!

Précédent, avec recherche, 49 octets

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

Essayez-le en ligne!

Précédent, avec réduction, 52 octets:

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

Essayez-le en ligne!

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 semble évident maintenant. Merci!
Pureferret

0

C # (Visual C # Interactive Compiler) , 51 octets

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

Essayez-le en ligne!

Ci-dessus est une fonction anonyme qui sort en modifiant un argument . La sortie est un tableau de 1 et de 0.

Vous trouverez ci-dessous une fonction récursive qui génère un entier.

C # (Visual C # Interactive Compiler) , 60 octets

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

Essayez-le en ligne!

Les deux fonctions prennent en entrée un tableau à 4 éléments.

[d, c, b, a]

Vous n'avez pas besoin de sortir un entier.
Adám

@Adam - merci :) Je l'ai réalisé après avoir posté alors que je travaillais sur mon autre réponse. Avant d'avoir la chance de changer, il y avait une autre réponse C # qui utilisait beaucoup de bonnes astuces.
dana



0

Lot, 92 octets

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

Prend les arguments comme paramètres de ligne de commande dans l'ordre inverse. Fonctionne en calculant arithmétiquement le maximum des paramètres en les réduisant et en ajoutant uniquement des différences positives par rapport au maximum en cours, puis en mappant à nouveau chaque paramètre cette fois en le comparant au maximum. De manière pratique, cmd/cset/ane produit pas de nouvelle ligne, donc les résultats sont automatiquement concaténés ensemble. Le %f%enregistre simplement 5 octets sur ce qui serait une construction répétée.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.