Progetta una funzione iniettiva commutativa tra qualsiasi set infinito (limitato) e coppie non ordinate


18

Correlati, ma ciò richiede solo numeri interi positivi e non deve essere commutativo

La funzione di abbinamento Cantor è descritta in questo articolo di Wikipedia . In sostanza, si tratta di un'operazione tale che quando viene applicato a due valori X e Y, si possono ottenere i valori originali X e Y in base al risultato.

Il tuo compito è progettare due funzioni: una che esegue X, Y -> Ze l'altra che esegue Z -> X, Y. Ecco il trucco: X, Y -> Zdeve essere commutativo. Ciò significa che Z -> X, Ynon sarà in grado di determinare se l'input era X, Yo Y, X.

La definizione formale di questa sfida sarebbe:

Scegli un insieme infinito numerabile S di numeri.
Progettare due funzioni che svolgono le seguenti attività:

  • Data una coppia non ordinata di valori in S, restituisce un valore in S
  • Dato un valore di ritorno dalla funzione iniziale, restituisce la coppia di valori non ordinata che restituisce il numero intero di input quando passa attraverso la prima funzione. Non mi interessa il comportamento di questa funzione inversa se l'input non è un valore restituito dalla prima funzione.

Requisiti

  • Il risultato dovrebbe essere identico tra le esecuzioni.
  • {a, a} è una coppia non ordinata

Nota: è più probabile che la tua risposta ottenga un mio voto se fornisci una prova, ma testerò le risposte quando la raggiungerò e la voterò una volta che sono abbastanza sicuro che funzioni.


Non si adatta meglio a puzzling.stackexchange.com ?
Jakube,

2
@Jakube Non necessariamente, poiché è necessario scrivere codice.
Mr. Xcoder,

Suppongo che le coppie siano univoche, ma i numeri utilizzati in quelle coppie non lo sono? Quindi, quando 1,2è una delle coppie, 1,3può anche essere una potenziale coppia (entrambi usano 1)?
Kevin Cruijssen,

@KevinCruijssen Non sono sicuro di cosa intendi
HyperNeutrino,

@Giuseppe L'inverso non deve essere in grado di restituire l'ordine corretto; è solo che per funzione fe il suo gsorted((x, y))sorted(g(f(x, y)))
contrario

Risposte:


13

Haskell , 65 + 30 = 95 byte

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

Provalo online!

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

Provalo online!


Nota: quando le due funzioni possono condividere il codice, questo è solo 75 byte:

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

Provalo online! Il dominio è numeri interi positivi. La funzione (#)esegue l'accoppiamento, la funzione è (l!!)inversa. Esempio di utilizzo: entrambi (#) 5 3e (#) 3 5rendimento 12e (l!!) 12rendimenti (5,3).

Funziona elencando esplicitamente tutte le coppie ordinate in un elenco infinito 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), ...`

La codifica è quindi solo l'indice in questo elenco.


dall'OP, il codice condiviso deve essere contato due volte
orgoglioso haskeller l'

5

Pyth , 8 + 6 = 14 byte

ij\aSQ16

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

Provalo online!

c.HQ\a

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

Provalo online!
Dominio: numeri interi positivi.


bel approccio! +1
HyperNeutrino,

4
Non funziona per molti numeri come 2e 10per esempio (che sono nel dominio)
Emigna

Sicuro. Esempio1 , Esempio2
Emigna

La seconda funzione dovrebbe funzionare per qualsiasi valore in S, non solo per quello che è stato generato con la prima funzione (ho fatto lo stesso errore).
Arnauld,

4

Gelatina , 8 + 11 = 19 byte

Eseguito il rollback poiché l'algoritmo di Rod non ha funzionato.

Funziona sul dominio degli interi positivi.

Prende xe ycome 2 argomenti, non importa in quale ordine, ritorna z.

»’RSð+ð«

Provalo online!

Prende ze ritorna[min(x, y), max(x, y)]

R€Ẏ,Rx`$ị@€

Provalo online!


1
Perché i downvotes? Questo non è l'algoritmo di Rod.
Erik the Outgolfer,

4

JavaScript (ES7), 44 byte

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

Mappa da numeri interi non negativi a un suo sottoinsieme.


4

C (gcc) , 36 + 39 = 75 byte

Grazie a @tsh per aver salvato due byte.

Il dominio è numeri interi non negativi.

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

Prende xe y, ritorna z.

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

Accetta una intmatrice a due elementi . Il secondo elemento deve essere impostato zprima della chiamata. Dopo che la chiamata rcontiene xe y.

Provalo online!


(x+1)->-~x
tsh

3

Gelatina , 13 11 byte

coppia di numeri interi positivi a numero intero positivo, 5 byte

Ṁc2+Ṃ

Provalo online!

numero intero positivo alla coppia di numeri interi positivi, 6 byte

ŒċṀÞị@

Provalo online!

Algoritmo

Se ordiniamo l'insieme di tutte le coppie non ordinate di numeri interi positivi per il loro massimo e quindi per la loro somma, otteniamo la seguente sequenza.

{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 prima funzione accetta una coppia {x, y} e trova il suo indice in questa sequenza.

La seconda funzione accetta un numero intero positivo z e restituisce z esimo elemento della sequenza.

Nota che questa mappatura è la stessa della risposta Jelly di @ EriktheOutgolfer .

Come funziona

Ṁ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
Spiegazione per favore. Non sono sicuro che questo sia valido ...
Erik the Outgolfer,

Ho aggiunto l'algoritmo.
Dennis,

Qualcosa non mi attacca bene ... anche se non sono sicuro che neanche questo sia valido. Fondamentalmente non si attacca bene se usi entrambi ce Œċ... anche se potrei sbagliarmi. A proposito, questa è stata la mia risposta che hai superato> _>
Erik the Outgolfer,

La differenza è minima per le coppie. Se C calcola le combinazioni senza sostituzione e Ƈ calcola le combinazioni con, nƇ2 = nC2 + n .
Dennis,

2

Mathematica (35 + 53) = 78 byte

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

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

Questa è l'unica nota funzione di associazione quadratica per Z <--> ZxZ combinata con Min e Max per renderla senza ordini.


2

Rubino, 66 byte

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

Sto cercando di trovare un modo per selezionare astutamente un set infinito per renderlo più facile, questo è il migliore che ho finora.

Definiamo f (x, y) = 2 x-1 bit a bit o 2 y-1 . Il dominio è costituito dall'insieme definito ricorsivamente come contenente 1,2 e tutti i numeri che possono essere prodotti chiamando f sui numeri nell'insieme (si noti che f (1,1) = 1 ef (2,2) = 2, quindi 1 e 2 hanno inversioni). Tutti i numeri risultanti hanno uno o due 1 nella loro espansione binaria, con gli indici degli 1 corrispondenti ai numeri nell'insieme. Possiamo ottenere la coppia originale non ordinata eliminando gli indici. Se c'è solo un 1, significa che gli elementi della coppia sono uguali.

Ad esempio, f (3,5) è 20, perché 20 è 10100 nella base 2, che ha 1s nel 3 ° e 5 ° posto meno significativo.



Grazie, S è in realtà un sottoinsieme di quella sequenza OEIS anche perché include solo numeri il cui 1 ha indici in S.
histocrat

ah sì, certo. Bene, nessun'altra sequenza corrisponde ai primi termini (fino a 32).
Giuseppe,

Aggiungi 0 a S e puoi salvare alcuni decrementi.
nwellnhof,

2

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

Funzione di accoppiamento

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

Provalo online!

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

Provalo online!


1
Puoi giocare a golf in alcune parti. Nella funzione di coppia: int i=(""+a[0]).length()può essere int i=(f+a[0]).length(); lo spazio tra c=0,j;i>0;può essere rimosso; a[0].parseIntpuò essere new Integer. Nella funzione depair: tutti e tre r.parseIntpossono essere r.decode; e potresti creare una variabile int per t.length(), poiché la usi due volte.
Kevin Cruijssen,


1

JavaScript, 72 byte

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

Funziona con numeri interi positivi (in teoria). Idea piuttosto semplice: ordina due numeri in un ordine (magico), collegali come stringa con una lettera "a", analizzali come numeri interi esadecimali.


1

MATL, 6 + 8 = 14 byte

Funzione di codifica, accetta due ingressi n, m. Emette il prodotto dell'ennesimo primo e dell'altro primo.

,iYq]*

passi:

  • , - Fai due volte
  • i - Push input
  • Yq - Pop input, push input'th prime
  • ]* - Termina due volte, fai saltare entrambi i numeri primi e spingi il prodotto

Funzione di decodifica, richiede un input m. Emette il numero di numeri primi al di sotto di ciascuno dei fattori primi di n.

iYf"@Zqn

passi:

  • i - Push input
  • Yf - Pop input, push array di fattori primi
  • " - Per n in array
  • @Zq - Spingere la matrice di numeri primi al di sotto di n
  • n - Pop array, push lunghezza dell'array

Questo è commutativo perché la moltiplicazione è commutativa e iniettiva perché le prime fattorizzazioni sono uniche. Non che questo non sia sugli interi.


0

Buccia , 5 + 3 = 8 byte

Spero davvero di aver capito bene la sfida, vedo alcune risposte cancellate che mi sembrano valide ...

Coppie di numeri interi positivi in ​​un singolo numero intero positivo:

¤*!İp

Provalo online!

Funziona prendendo i numeri degli indici indicati (1-indicizzati) dall'elenco dei numeri primi e moltiplicandoli.

Risultato della prima funzione per coppie di numeri interi positivi:

mṗp

Provalo online!

Fattorizziamo il numero di input e restituiamo l'indice nell'elenco dei numeri primi di tutti (entrambi) i suoi fattori.

Esempio lavorato

Dato (4,1)come una coppia iniziale, prendiamo il quarto e il primo numero primo (7,2)e li moltiplichiamo → 14. Questa moltiplicazione è ciò che rende la funzione indipendente dall'ordine dei due elementi.

A partire da 14, lo fattorizziamo (2,7)e restituiamo gli indici di 2e 7nell'elenco dei numeri primi → (1,4).


In realtà, guardando la risposta cancellata da Arnauld, il suo algoritmo è ancora migliore e il porting su Husk comporterebbe 6 byte ... Qualcuno potrebbe confermare se la sua soluzione (e anche la mia) è valida o no?
Leone,

Non funziona per i numeri primi (che sono nel dominio di numeri interi positivi)
Emigna,

@Emigna la seconda funzione non funziona, ma i primi non vengono mai restituiti dalla prima ...
Leone,

Il tuo dominio è numeri interi positivi, quindi entrambi i metodi devono funzionare con numeri interi positivi. EDIT: o almeno quello era un requisito. Le regole attuali sembrano consentire un sottoinsieme del dominio.
Emigna,

0

C # , 80 byte (38 + 42)


Dati

Codificatore

  • Immettere Int32 l un numero
  • Immettere Int32 r un numero
  • Uscita Int64 Entrambi gli ingressi sono stati fusi insieme

decoder

  • Input Int32 v Il valore
  • Output Int32[] Un array con i due ints originali.

golfed

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

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

Ungolfed

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

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

Leggibile non golfato

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

Codice completo

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 )} ]" );
        }
    }
}

Uscite

  • v1.0 - 80 bytes- Soluzione iniziale.

Appunti

  • Nessuna

0

Python: 41 + 45 = 86

encoder: 41

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

(11110111, 11110111)

decodificatore: 45

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

[4, 3]

Tentativo precedente:

Python: 114: 30 + 84

encoder: 30

accetta 2 numeri interi, restituisce una stringa

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

(432, 432)

decodificatore: 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

decoder2: 120

un altro tentativo con comprensione e somma del generatore

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
basato sul secondo tentativo: e=lambda*x:10**sum(x)-10**min(x);d=lambda z:map(z .count,'09'); TIO
TSH

@tsh molto bello. Lo adatterò più tardi, oppure puoi inviare la tua risposta
Maarten Fabré,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.