Concevoir une fonction d'injection commutative entre tout ensemble infini (restreint) et ses paires non ordonnées


18

Associé, mais cela ne nécessite que des nombres entiers positifs et ne doit pas être commutatif

La fonction de couplage Cantor est décrite dans cet article Wikipedia . Il s'agit essentiellement d'une opération telle que lorsqu'elle est appliquée à deux valeurs X et Y, on peut obtenir les valeurs d'origine X et Y compte tenu du résultat.

Votre tâche consiste à concevoir deux fonctions: l'une qui fonctionne X, Y -> Zet l'autre qui fonctionne Z -> X, Y. Voici le hic: X, Y -> Zdoit être commutatif. Cela signifie que vous Z -> X, Yne pourrez pas déterminer si l'entrée était X, You Y, X.

La définition officielle de ce défi serait:

Choisissez un ensemble infini dénombrable S de nombres.
Concevez deux fonctions qui effectuent les tâches suivantes:

  • Étant donné une paire de valeurs non ordonnée dans S, renvoyer une valeur dans S
  • Étant donné une valeur de retour de la fonction initiale, renvoyez la paire de valeurs non ordonnée qui est évaluée à l'entier d'entrée lorsqu'elle est passée par la première fonction. Je me fiche du comportement de cette fonction inverse si l'entrée n'est pas une valeur de retour de la première fonction.

Exigences

  • Le résultat doit être identique entre les exécutions.
  • {a, a} est une paire non ordonnée

Remarque: votre réponse est plus susceptible d'obtenir un vote positif de ma part si vous fournissez une preuve, mais je testerai les réponses dès que j'y arriverai et je voterai une fois que je suis assez sûr que cela fonctionne.


Cela ne convient-il pas mieux à puzzling.stackexchange.com ?
Jakube

2
@Jakube Pas nécessairement, car vous devez écrire du code.
M. Xcoder

Je suppose que les paires sont uniques, mais les nombres utilisés dans ces paires ne le sont pas? Alors, quand 1,2est l'une des paires, 1,3peut également être une paire potentielle (les deux utilisent 1)?
Kevin Cruijssen

@KevinCruijssen Je ne sais pas trop ce que tu veux dire
HyperNeutrino

@Giuseppe L'inverse n'a pas besoin de pouvoir renvoyer la commande correcte; c'est juste que pour la fonction fet son inverse g, sorted((x, y))devrait être le même quesorted(g(f(x, y)))
HyperNeutrino

Réponses:


13

Haskell , 65 + 30 = 95 octets

a#b=length.fst$span(<(max a b,min a b))[(a,b)|a<-[1..],b<-[1..a]]

Essayez-le en ligne!

([(a,b)|a<-[1..],b<-[1..a]]!!)

Essayez-le en ligne!


Remarque: lorsque les deux fonctions peuvent partager du code, cela ne représente que 75 octets:

(l!!)
a#b=length.fst$span(<(max a b,min a b))l
l=[(a,b)|a<-[1..],b<-[1..a]]

Essayez-le en ligne! Le domaine est les entiers positifs. La fonction (#)effectue l'appariement, la fonction (l!!)son inverse. Exemple d'utilisation: Both (#) 5 3et (#) 3 5yield 12, and (l!!) 12yields (5,3).

Cela fonctionne en listant explicitement toutes les paires triées dans une liste infinie l:

l = [(1,1),(2,1),(2,2),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3),(4,4),(5,1),(5,2),(5,3),(5,4),(5,5),(6,1), ...`

L'encodage n'est alors que l'index de cette liste.


par le PO, le code partagé doit être compté deux fois
fier haskeller

5

Pyth , 8 + 6 = 14 octets

ij\aSQ16

    SQ   # Sort the input
 j\a     # join with "a"
i     16 # convert from base 16 to base 10

Essayez-le en ligne!

c.HQ\a

 .HQ     # convert from base 10 to 16
c   \a   # split on "a"

Essayez-le en ligne!
Domaine: entiers positifs.


belle approche! +1
HyperNeutrino

4
Ne fonctionne pas pour beaucoup de numéros comme 2et 10par exemple (qui sont dans le domaine)
Emigna


La 2ème fonction est censée fonctionner pour n'importe quelle valeur dans S, pas seulement celle qui a été générée avec la première fonction (j'ai fait la même erreur).
Arnauld


4

JavaScript (ES7), 44 octets

(x,y)=>x>y?x*x+y:y*y+x
z=>[x=z**.5|0,y=z-x*x]

Mappe des entiers non négatifs à un sous-ensemble de ceux-ci.


4

C (gcc) , 36 + 39 = 75 octets

Merci à @tsh d'avoir économisé deux octets.

Le domaine est composé d'entiers non négatifs.

p(x,y){return y>x?p(y,x):-~x*x/2+y;}

Prend xet yretourne z.

u(int*r){for(*r=0;r[1]>*r;r[1]-=++*r);}

Prend un inttableau à deux éléments . Le deuxième élément doit être défini sur zavant l'appel. Après l'appel rcontient xet y.

Essayez-le en ligne!


(x+1)->-~x
tsh

3

Gelée , 13 11 octets

paire d'entiers positifs à entier positif, 5 octets

Ṁc2+Ṃ

Essayez-le en ligne!

entier positif à une paire d'entiers positifs, 6 octets

ŒċṀÞị@

Essayez-le en ligne!

Algorithme

Si nous trions l'ensemble de toutes les paires d'entiers positifs non ordonnées par leur maximum puis par leur somme, nous obtenons la séquence suivante.

{1,1}, {1,2}, {2,2}, {1,3}, {2,3}, {3,3}, {1,4}, {2,4}, {3 , 4}, {4,4}, {1,5}, {2,5}, {3,5}, {4,5}, {5,5},…

La première fonction prend une paire {x, y} et trouve son index dans cette séquence.

La deuxième fonction prend un entier positif z et retourne le z ème élément de la séquence.

Notez que ce mappage est le même que dans la réponse Jelly de @ EriktheOutgolfer .

Comment ça fonctionne

Ṁc2+Ṃ   Main link. Argument: [x, y]
        Let m = max(x, y) and n = min(x, y).

Ṁ       Maximum; yield m.
 c2     2-combinations; yield mC2 = m(m-1)/2.
        Note that there's one pair with maximum 1 ({1,1}), two pairs with maximum 2
        ({1,2}, {2,2}), etc., so there are 1 + 2 + … + (m-1) = m(m-1)/2 pairs with
        maximum less than m.
    Ṃ   Minimum; yield n.
        Note that {x,y} is the n-th pair with maximum m.
   +    Add; yield mC2 + n.
        This finds {x,y}'s index in the sequence.
ŒċṀÞị@  Main link. Argument: z

Œċ      2-combinations w/replacement; yield all pairs [x, y] such that x ≤ y ≤ z.
  ṀÞ    Sort by maximum.
    ị@  Retrieve the pair at index z (1-based).

2
Explication s'il vous plaît. Je ne suis pas sûr que ce soit valide ...
Erik the Outgolfer

J'ai ajouté l'algorithme.
Dennis

Quelque chose ne me colle pas bien ... même si je ne suis pas sûr que ce soit invalide non plus. Fondamentalement, cela ne colle pas bien que vous utilisez les deux cet Œċ... bien que je puisse me tromper. BTW c'était ma réponse que vous avez surpassé> _>
Erik l'Outgolfer

La différence est minime pour les paires. Si C calcule des combinaisons sans remplacement et Ƈ calcule des combinaisons avec, nƇ2 = nC2 + n .
Dennis

2

Mathematica (35 + 53) = 78 octets

((x=Min[#])+(y=Max[#]))(x+y+1)/2+y&

(i=Floor[(-1+Sqrt[1+8#])/2];{#-i(1+i)/2,i(3+i)/2-#})&

C'est la seule bonne fonction d'appariement quadratique connue pour Z <--> ZxZ combinée avec Min et Max pour la rendre sans ordre.


2

Rubis, 66 octets

f=->x,y{2**~-x|2**~-y}
g=->n{x,y=(1..n).select{|i|n[i-1]>0};[x,y||x]}

J'essaie de trouver un moyen de sélectionner astucieusement un ensemble infini pour rendre cela plus facile, c'est le meilleur que j'ai à ce jour.

On définit f (x, y) = 2 x-1 au niveau du bit ou 2 y-1 . Le domaine se compose de l'ensemble défini récursivement comme contenant 1,2 et de tous les nombres qui peuvent être produits en appelant f aux nombres de l'ensemble (notez que f (1,1) = 1 et f (2,2) = 2, donc 1 et 2 ont des inverses). Les nombres résultants ont tous un ou deux 1 dans leur expansion binaire, les indices des 1 correspondant aux nombres de l'ensemble. Nous pouvons obtenir la paire non ordonnée d'origine en prenant les indices. S'il n'y a qu'un seul 1, cela signifie que les éléments de la paire sont égaux.

Par exemple, f (3,5) est 20, car 20 est 10100 en base 2, qui a 1s aux 3e et 5e places les moins significatives.



Merci, S est en fait un sous-ensemble de cette séquence OEIS car il ne comprend que des nombres dont les 1 ont des index dans S.
histocrat

ah oui, bien sûr. Eh bien, aucune autre séquence ne correspond aux premiers termes (jusqu'à 32).
Giuseppe

Ajoutez 0 à S et vous pouvez enregistrer quelques diminutions.
nwellnhof

2

Java 8, 153 146 141 137 + 268 224 216 205 octets

Fonction paire

a->{String f="";for(int i=(f+a[0]).length(),c=0,j;i>0;i-=c,f+=c,c=0)for(j=1;j<10;c+=i-j++<0?0:1);return new Integer(a[0]+""+a[1]+"0"+f);}

Essayez-le en ligne!

Fonction Depair

r->{String a=r+"",t=a.substring(a.lastIndexOf('0')+1);int l=0,i=l,o=t.length();for(;i<o;l+=r.decode(t.charAt(i++)+""));return new int[]{r.decode(a.substring(0,l)),r.decode(a.substring(l,a.length()-o-1))};}

Essayez-le en ligne!


1
Vous pouvez jouer au golf quelques parties. Dans la fonction paire: int i=(""+a[0]).length()peut être int i=(f+a[0]).length(); l'espace entre c=0,j;i>0;peut être supprimé; a[0].parseIntpeut être new Integer. Dans la fonction dépair: les trois r.parseIntpeuvent être r.decode; et vous pouvez créer une variable int pour t.length(), puisque vous l'utilisez deux fois.
Kevin Cruijssen


1

JavaScript, 72 octets

f=a=>eval('0x'+a.sort().join`a`)
g=n=>n.toString(16).split`a`.map(x=>+x)

Fonctionne pour les entiers positifs (en théorie). Idée assez simple: trier deux nombres dans un certain ordre (magique), les connecter sous forme de chaîne par une lettre "a", les analyser en entier hexadécimal.


1

MATL, 6 + 8 = 14 octets

Fonction d'encodage, prend deux entrées n, m. Produit le produit du nième premier et du mième premier.

,iYq]*

Pas:

  • , - Faites deux fois
  • i - Entrée push
  • Yq - Entrée pop, entrée push'th prime
  • ]* - Finissez deux fois, éclatez les deux nombres premiers et poussez le produit

Fonction de décodage, prend une entrée m. Génère le nombre de nombres premiers en dessous de chacun des facteurs premiers de n.

iYf"@Zqn

Pas:

  • i - Entrée push
  • Yf - Entrée pop, push tableau de facteurs premiers
  • " - Pour n dans le tableau
  • @Zq - Poussez le tableau de nombres premiers en dessous de n
  • n - Tableau pop, longueur push du tableau

Ceci est commutatif parce que la multiplication est commutative et injectif parce que les factorisations premières sont uniques. Non pas que ce ne soit pas sur les entiers.


0

Coque , 5 + 3 = 8 octets

J'espère vraiment avoir relevé le défi, je vois des réponses supprimées qui me semblent valables ...

Couples d'entiers positifs à un seul entier positif:

¤*!İp

Essayez-le en ligne!

Il fonctionne en prenant les nombres aux indices donnés (indexés 1) dans la liste des nombres premiers et en les multipliant.

Résultat de la première fonction aux couples d'entiers positifs:

mṗp

Essayez-le en ligne!

Nous factorisons le nombre d'entrée et renvoyons l'index dans la liste des nombres premiers de tous (les deux) de ses facteurs.

Exemple travaillé

Étant donné (4,1)un couple de départ, nous prenons les quatrième et premier nombres premiers (7,2)et les multiplions → 14. Cette multiplication est ce qui rend la fonction indépendante de l'ordre des deux éléments.

À partir de 14, nous le factorisons (2,7)et retournons les indices de 2et 7dans la liste des nombres premiers → (1,4).


En fait, en regardant la réponse supprimée d'Arnauld, son algorithme est encore meilleur, et le porter sur Husk entraînerait 6 octets ... Quelqu'un pourrait-il confirmer si sa solution (et la mienne aussi) est valide ou non?
Leo

Ne fonctionne pas pour les nombres premiers (qui sont dans le domaine des entiers positifs)
Emigna

@Emigna, la deuxième fonction ne fonctionne pas, mais les nombres premiers ne sont jamais renvoyés par la première ...
Leo

Votre domaine est composé d'entiers positifs, les deux méthodes doivent donc fonctionner pour des entiers positifs. EDIT: ou du moins c'était une exigence. Les règles actuelles semblent autoriser un sous-ensemble du domaine.
Emigna

0

C # , 80 octets (38 + 42)


Les données

Encodeur

  • Contribution Int32 l un nombre
  • Contribution Int32 r un nombre
  • Sortie Int64 Les deux entrées fusionnées ensemble

Décodeur

  • Contribution Int32 v la valeur
  • Sortie Int32[] Un tableau avec les deux entrées d'origine.

Golfé

// Encoder
e=(l,r)=>{return(long)l<<32|(uint)r;};

// Decoder
d=v=>{return new[]{v>>32,v&0xFFFFFFFFL};};

Non golfé

// Encoder
e = ( l, r ) => {
    return (long) l << 32 | (uint) r;
};

// Decoder
d = v => {
    return new[] {
        v >> 32,
        v & 0xFFFFFFFFL };
};

Non lisible non lisible

// Encoder
// Takes a pair of ints
e = ( l, r ) => {

    // Returns the ints fused together in a long where the first 32 bits are the first int
    // and the last 32 bits the second int
    return (long) l << 32 | (uint) r;
};

// Decoder
// Takes a long
d = v => {

    // Returns an array with the ints decoded where...
    return new[] {

        // ... the first 32 bits are the first int...
        v >> 32,

        // ... and the last 32 bits the second int
        v & 0xFFFFFFFFL };
};

Code complet

using System;
using System.Collections.Generic;

namespace TestBench {
    public class Program {
        // Methods
        static void Main( string[] args ) {
            Func<Int32, Int32, Int64> e = ( l, r ) => {
                return(long) l << 32 | (uint) r;
            };
            Func<Int64, Int64[]> d = v => {
                return new[] { v >> 32, v & 0xFFFFFFFFL };
            };

            List<KeyValuePair<Int32, Int32>>
                testCases = new List<KeyValuePair<Int32, Int32>>() {
                    new KeyValuePair<Int32, Int32>( 13, 897 ),
                    new KeyValuePair<Int32, Int32>( 54234, 0 ),
                    new KeyValuePair<Int32, Int32>( 0, 0 ),
                    new KeyValuePair<Int32, Int32>( 1, 1 ),
                    new KeyValuePair<Int32, Int32>( 615234, 1223343 ),
                };

            foreach( KeyValuePair<Int32, Int32> testCase in testCases ) {
                Console.WriteLine( $" ENCODER: {testCase.Key}, {testCase.Value} = {e( testCase.Key, testCase.Value )}" );
                Console.Write( $"DECODING: {e( testCase.Key, testCase.Value )} = " );
                PrintArray( d( e( testCase.Key, testCase.Value ) ) );

                Console.WriteLine();
            }

            Console.ReadLine();
        }

        public static void PrintArray<TSource>( TSource[] array ) {
            PrintArray( array, o => o.ToString() );
        }
        public static void PrintArray<TSource>( TSource[] array, Func<TSource, String> valueFetcher ) {
            List<String>
                output = new List<String>();

            for( Int32 index = 0; index < array.Length; index++ ) {
                output.Add( valueFetcher( array[ index ] ) );
            }

            Console.WriteLine( $"[ {String.Join( ", ", output )} ]" );
        }
    }
}

Communiqués

  • v1.0 - 80 bytes- Solution initiale.

Remarques

  • Aucun

0

Python: 41 + 45 = 86

encodeur: 41

e=lambda*x:int('1'*max(x)+'0'+'1'*min(x))
e(4, 3), e(3,4)

(11110111, 11110111)

décodeur: 45

d=lambda z:[len(i)for i in str(z).split('0')]
d(11110111)

[4, 3]

Tentative plus ancienne:

Python: 114: 30 + 84

encodeur: 30

accepte 2 entiers, retourne une chaîne

e=lambda*x:2**max(x)*3**min(x)
e(3, 4), e(4, 3)

(432, 432)

décodeur: 86

def d(z):
 x=y=0
 while 1-z%2:
  x+=1
  z/=2
 while 1-z%3:
  y+=1
  z/=3
 return x,y
d(432)

4, 3

décodeur2: 120

une autre tentative avec des compréhensions de générateur et somme

def d(z):
 x=sum(1 for i in range(z)if not z%(2**i))-1
 z/=2**x
 return x,sum(1 for i in range(int(z))if not z%(3**i))-1

1
basé sur la deuxième tentative: e=lambda*x:10**sum(x)-10**min(x);d=lambda z:map(z .count,'09'); TIO
tsh

@tsh très sympa. Je l'adapterai plus tard, ou vous pouvez soumettre votre propre réponse
Maarten Fabré
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.