在任意(受限制的)无穷集与无序对之间设计一个交换式内射函数


18

相关,但这只需要正整数,而不必是可交换的

Cantor配对功能在此Wikipedia文章中进行了描述。本质上,这是一种操作,当将其应用于两个值X和Y时,只要给出结果,就可以获得原始值X和Y。

您的任务是设计两个功能:一个执行X, Y -> Z,另一个执行Z -> X, YX, Y -> Z要注意的是:必须是可交换的。这意味着Z -> X, Y将无法确定输入是X, Y还是Y, X

这个挑战的正式定义是:

选择一个可数的无穷大数字S。
设计执行以下任务的两个功能:

  • 给定S中的无序值对,则返回S中的值
  • 给定初始函数的返回值,返回无序的一对值,当通过第一个函数时,该值对将得出输入整数。如果输入不是第一个函数的返回值,则我不关心此反函数的行为。

要求

  • 运行之间的结果应相同。
  • {a, a} 是无序对

注意:如果您提供证据,您的答案更有可能获得我的支持,但是当我获得答案时,我会进行测试,并在相当确定的情况下对其进行支持。


这不适合puzzling.stackexchange.com吗?
雅库布

2
@Jakube不一定,因为您需要编写代码。
Xcoder先生17年

我假设对是唯一的,但是这些对中使用的数字不是吗?那么何时1,2是一对,1,3也可以是一个潜在的对(都使用1)?
凯文·克鲁伊森

@KevinCruijssen我不确定您的意思
HyperNeutrino

@Giuseppe逆不需要能够返回正确的顺序。只是对于函数f及其逆函数gsorted((x, y))应该与sorted(g(f(x, y)))
HyperNeutrino

Answers:


13

Haskell,65 + 30 = 95字节

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

在线尝试!

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

在线尝试!


注意:当两个函数可以共享代码时,这只有75个字节:

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

在线尝试!该域是正整数。函数(#)执行配对,函数执行(l!!)反函数。用法示例:(#) 5 3(#) 3 5yield 12,以及(l!!) 12yields (5,3)

这通过在无限列表中显式列出所有排序对来起作用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), ...`

然后,编码只是该列表中的索引。


通过OP,共享代码必须计算两次
骄傲的haskeller

5

Pyth,8 + 6 = 14个字节

ij\aSQ16

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

在线尝试!

c.HQ\a

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

在线尝试!
域:正整数。


不错的方法!+1
HyperNeutrino

4
不适用于许多数字,例如210(在域中)
Emigna


第二个函数应该适用于S中的任何值,而不仅仅是第一个函数生成的值(我犯了同样的错误)。
Arnauld


4

JavaScript(ES7),44个字节

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

从非负整数到其子集的映射。


4

C(gcc),36 + 39 = 75字节

感谢@tsh节省了两个字节。

域是非负整数。

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

xy返回z

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

带有两个元素的int数组。必须z在调用之前将第二个元素设置为。通话r包含x和之后y

在线尝试!


(x+1)->-~x
tsh

3

果冻13 11字节

正整数到正整数对,5个字节

Ṁc2+Ṃ

在线尝试!

正整数到正整数对,6个字节

ŒċṀÞị@

在线尝试!

算法

如果我们按其最大值然后按它们的总和对所有无序的正整数对的集合进行排序,则会得到以下序列。

{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},...

第一个函数采用一对{x,y}并按此顺序查找其索引。

第二个函数取一个正整数 z并返回序列的z 项目。

请注意,此映射与@EriktheOutgolfer的Jelly answer中的映射相同。

怎么运行的

Ṁ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
请解释。我不确定这是有效的...
Erik the Outgolfer

我已经添加了算法。
丹尼斯,

有些东西对我不好,虽然我不确定这是否无效。基本上,您同时使用这两种方法c并不能很好地保持Œċ...尽管我可能错了。顺便说一句,这就是我的回答,你出了问题> _>
Egg the Outgolfer

对的差异很小。如果C计算不带替换的组合,而Ƈ计算具有的组合,则nƇ2= nC2 + n
丹尼斯

2

Mathematica(35 + 53)= 78字节

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

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

这是Z <-> ZxZ与Min和Max相结合以使其无序的一种众所周知的二次配对函数。


2

Ruby,66个字节

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

我正在尝试寻找一种方法来巧妙地选择一个无限的集合,以使其更容易,这是到目前为止我所能做到的最好的。

我们定义f(x,y)= 2 x-1按位或2 y-1。域包括递归定义为包含1,2的集合,以及可以通过对集合中的数字调用f产生的所有数字(请注意,f(1,1)= 1和f(2,2)= 2,因此1和2具有反函数)。结果数字在二进制扩展中都具有一个或两个1,并且1的索引对应于集合中的数字。我们可以通过获取索引来获得原始的无序对。如果只有一个1,则表示该对元素相等。

例如,f(3,5)为20,因为在基数2中20为10100,在第3和第5个最低有效位具有1。



谢谢,S实际上是OEIS序列的子集,但因为它仅包括其1S在S.索引号
histocrat

是的,当然。好吧,没有其他序列匹配前几个项(最多32个)。
Giuseppe

将S加0,您可以保存一些减量。
nwellnhof

2

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

配对功能

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

在线尝试!

维修功能

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

在线尝试!


1
您可以打高尔夫球。在对函数中:int i=(""+a[0]).length()可以int i=(f+a[0]).length();之间的空间c=0,j;i>0;可以删除;a[0].parseInt可以new Integer。在depair功能中:这三个r.parseInt都可以r.decode;您可以为设置一个int变量t.length(),因为您使用了两次。
凯文·克鲁伊森


1

JavaScript,72个字节

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

适用于正整数(理论上)。很简单的想法:以某种(魔术)顺序对两个数字进行排序,用字母将它们连接成字符串,然后将其"a"解析为十六进制整数。


1

MATL,6 + 8 = 14个字节

编码功能,需要两个输入n,m。输出第n个素数和第m个素数的乘积。

,iYq]*

脚步:

  • , -做两次
  • i -推送输入
  • Yq -弹出输入,按入素数
  • ]* -结束两次,弹出素数并推积

解码功能,需要一个输入m。输出n的每个素数以下的素数。

iYf"@Zqn

脚步:

  • i -推送输入
  • Yf -弹出式输入,推送主要因素数组
  • " -对于数组中的n
  • @Zq -将素数数组推到n以下
  • n -弹出数组,推送数组的长度

这是可交换的,因为乘法是可交换的,而可射式是因为素因数分解是唯一的。并不是说这不是整数。


0

稻壳,5 + 3 = 8字节

我真的希望我能正确应对挑战,我发现一些删除的答案对我来说似乎很有效...

正整数对与单个正整数的对:

¤*!İp

在线尝试!

它通过从质数列表中获取给定索引(1索引)处的数字并将它们相乘来工作。

第一个函数对正整数对的结果:

mṗp

在线尝试!

我们将输入数字分解,并返回所有(两个)因子的质数列表中的索引。

工作的例子

给定(4,1)一个初始对,我们将第四个和第一个质数(7,2)乘以→ 14。这种乘法使得函数在两个元素的顺序上是独立的。

从开始14,我们因式分解它(2,7),并返回的指标2,并7在质数→列表(1,4)


实际上,查看从Arnauld删除的答案,它的算法甚至更好,将其移植到Husk将导致6个字节……有人可以确认其解决方案(也是我的)是否有效?
Leo

不适用于素数(在正整数范围内)
Emigna

@Emigna第二个函数没有,但是第一个函数永远不会返回素数……
Leo

您的域是正整数,因此这两种方法都需要对正整数起作用。编辑:或至少以前是一个要求。当前规则似乎允许该域的子集。
Emigna

0

C#,80个字节(38 + 42)


数据

编码器

  • 输入项 Int32 l一个数字
  • 输入项 Int32 r一个数字
  • 输出量 Int64两个整数融合在一起

解码器

  • 输入项 Int32 v
  • 输出 Int32[]具有两个原始int的数组。

打高尔夫球

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

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

不打高尔夫球

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

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

非高尔夫可读

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

完整代码

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

发布

  • 1.0 - 80 bytes-初始溶液。

笔记

  • 没有

0

蟒蛇:41 + 45 = 86

编码器:41

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

(11110111,11110111)

解码器:45

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

[4,3]

较早的尝试:

Python:114:30 + 84

编码器:30

接受2个整数,返回一个字符串

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

(432,432)

解码器: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

解码器2:120

生成器理解和求和的另一种尝试

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
基于第二次尝试:e=lambda*x:10**sum(x)-10**min(x);d=lambda z:map(z .count,'09')TIO
tsh

@tsh很好。稍后我会进行调整,或者您可以提交自己的答案
MaartenFabré17年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.