अद्वितीय और निर्धारक तरीके से, दो पूर्णांकों को एक में मैप करना


235

दो सकारात्मक पूर्णांक ए और बी की कल्पना करें मैं इन दोनों को एक पूर्णांक सी में संयोजित करना चाहता हूं।

कोई अन्य पूर्णांक डी और ई नहीं हो सकता है जो सी के साथ गठबंधन करता है। इसलिए उन्हें जोड़ने के साथ ही ऑपरेटर के काम नहीं करता है। जैसे ३० + १० = ४० = ४० + ० = ३ ९ + १ न तो संघनन कार्य करता है। जैसे "31" + "2" = 312 = "3" + "12"

यह संयोजन ऑपरेशन भी नियतात्मक होना चाहिए (हमेशा एक ही इनपुट के साथ एक ही परिणाम प्राप्त करें) और हमेशा पूर्णांक के सकारात्मक या नकारात्मक पक्ष पर एक पूर्णांक उत्पन्न करना चाहिए।


10
यदि आपको सॉफ़्टवेयर में पूर्णांक या गणित में पूर्णांक से मतलब है तो आपको स्पष्ट करना चाहिए। सॉफ्टवेयर में, आप किसी भी पूर्णांक प्रकार को चुनते हैं और इसका आकार होगा, इसलिए आपके पास उनकी एक सीमित संख्या है, इसलिए कोई समाधान नहीं है (जब तक, निश्चित रूप से, आपके इनपुट डेटा को कुछ सीमा के भीतर होने की गारंटी है और आपका आउटपुट हो सकता है कोई भी पूर्णांक)। गणित में एस्क का समाधान देखें।
डैनियल डारानास

मैं एक कम, सकारात्मक सीमा में बंधे पूर्णांक के बारे में बात कर रहा हूं। ० से १०,००० तक कहे
नुकसान

27
@ शर्मा: तो कैसे बस के बारे में 10,001*A + B?
ब्लूराजा - डैनी पफ्लुगुएफ्ट

2
मुझे यह PHP फ़ंक्शंस मिला है: gist.github.com/hannesl/8031402
cakan

यदि आदेश मायने नहीं रखता है जैसे: (3,12) और (12,3) एक ही परिणाम देते हैं, तो मैं "A + B" + "A * B" का उपयोग करता
हूं

जवाबों:


233

आप एक विशेषण NxN -> Nमानचित्रण की तलाश कर रहे हैं । ये उदाहरण के लिए dovetailing के लिए उपयोग किया जाता है । पर एक नजर डालें इस पीडीएफ तथाकथित के परिचय के लिए जोड़ी कार्यों । विकिपीडिया एक विशिष्ट युग्मन फ़ंक्शन का नाम देता है, जिसका नाम कैंटर पेयरिंग फ़ंक्शन है :

pi (k1, k2) = 1/2 (k1 + k2) (k1 + k2 + 1) + p2

तीन टिप्पणियाँ:

  • जैसा कि अन्य ने स्पष्ट किया है, यदि आप एक युग्मन कार्य को लागू करने की योजना बनाते हैं, तो आप जल्द ही पा सकते हैं कि आपको मनमाने ढंग से बड़े पूर्णांक (bignar) की आवश्यकता है।
  • यदि आप जोड़े (ए, बी) और (बी) के बीच अंतर नहीं करना चाहते हैं, तो युग्मन फ़ंक्शन को लागू करने से पहले ए और बी को सॉर्ट करें।
  • दरअसल मैंने झूठ बोला था। आप एक विशेषण ZxZ -> Nमानचित्रण की तलाश कर रहे हैं । कैंटर का कार्य केवल गैर-नकारात्मक संख्याओं पर काम करता है। हालाँकि यह कोई समस्या नहीं है, क्योंकि एक जीव को परिभाषित करना आसान है f : Z -> N, जैसे:
    • f (n) = n * 2 अगर n> = 0
    • f (n) = -n * 2 - 1 यदि n <0

13
+1 मुझे लगता है कि यह अनबाउंड पूर्णांक के लिए सही उत्तर है।
अज्ञात

4
मैं फिर से k1, k2 का मान कैसे प्राप्त कर सकता हूं?
मीनूमास्टर

3
@MinuMaster: एक ही विकिपीडिया लेख में वर्णित है, कैंटर पेयरिंग फ़ंक्शन को इन्वर्ट करने के तहत ।
Stephan202

4
ज़ुडज़िक का कार्य भी देखें, जिसे न्यूफ़ल ने नीचे समझाया है।
ओलीजेजी

1
हालांकि यह अनबाउंड पूर्णांक के लिए सही है, यह पूर्णांक पूर्णांक के लिए सर्वोत्तम नहीं है। मुझे लगता है कि @ ब्लू-राज की टिप्पणी अब तक सबसे अधिक समझ में आती है।
कर्दासीस

226

कैंटर पेयरिंग फंक्शन वास्तव में बेहतर लोगों में से एक है, जो इसके सरल, तेज और अंतरिक्ष कुशल पर विचार कर रहा है, लेकिन मैथ्यू स्ज़्ज़िक द्वारा वुल्फराम में कुछ और भी बेहतर प्रकाशित किया गया है । कैंटर पेयरिंग फ़ंक्शन (अपेक्षाकृत) की सीमा यह है कि एन्कोडेड परिणामों की सीमा हमेशा 2Nबिट पूर्णांक की सीमा के भीतर नहीं रहती है यदि इनपुट दो Nबिट पूर्णांक होते हैं। यही है, अगर मेरे इनपुट दो 16बिट पूर्णांक हैं 0 to 2^16 -1, तो 2^16 * (2^16 -1)इनपुट के संयोजन संभव हैं, इसलिए स्पष्ट पिजनहोल सिद्धांत द्वारा , हमें कम से कम आकार का एक आउटपुट चाहिए 2^16 * (2^16 -1), जो कि समान है 2^32 - 2^16, या दूसरे शब्दों में, का एक नक्शा32बिट संख्या आदर्श रूप से संभव होनी चाहिए। यह प्रोग्रामिंग की दुनिया में बहुत कम व्यावहारिक महत्व नहीं हो सकता है।

कैंटर बाँधने का कार्य :

(a + b) * (a + b + 1) / 2 + a; where a, b >= 0

दो अधिकतम 16 बिट पूर्णांक (65535, 65535) के लिए मैपिंग 8589803520 होगी जो कि आप देखते हैं कि 32 बिट्स में फिट नहीं किया जा सकता है।

दर्ज करें Szudzik का कार्य :

a >= b ? a * a + a + b : a + b * b;  where a, b >= 0

(65535, 65535) मानचित्रण अब 4294967295 होगा, जैसा कि आप देख रहे हैं कि 32 बिट (0 से 2 ^ 32 -1) पूर्णांक है। यह वह जगह है जहां यह समाधान आदर्श है, यह बस उस स्थान में हर एक बिंदु का उपयोग करता है, इसलिए कुछ भी अधिक कुशल स्थान प्राप्त नहीं कर सकता है।


अब इस तथ्य पर विचार करते हुए कि हम आम तौर पर भाषाओं / रूपरेखाओं में विभिन्न आकारों की संख्याओं के हस्ताक्षरित कार्यान्वयन के साथ सौदा करते हैं, आइए signed 16बिट बिटर्स से लेकर विचार करें -(2^15) to 2^15 -1(बाद में हम देखेंगे कि हस्ताक्षरित सीमा पर भी कहां तक ​​विस्तार करना है)। कब से aऔर bसकारात्मक होना है, वे किस सीमा तक हैं 0 to 2^15 - 1

कैंटर बाँधने का कार्य :

दो अधिकतम 16 बिट हस्ताक्षरित पूर्णांक (32767, 32767) के लिए मैपिंग 2147418112 होगी जो हस्ताक्षरित 32 बिट पूर्णांक के लिए अधिकतम मूल्य से कुछ ही कम है।

अब ज़ुदज़िक का कार्य :

(32767, 32767) => 1073741823, बहुत छोटा ।।

चलो नकारात्मक पूर्णांक के लिए खाता है। यह मेरे द्वारा ज्ञात मूल प्रश्न से परे है, लेकिन भविष्य के आगंतुकों की मदद करने के लिए विस्तृत है।

कैंटर बाँधने का कार्य :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
(A + B) * (A + B + 1) / 2 + A;

(-32768, -32768) => 8589803520 जो कि Int64 है। 16 बिट इनपुट के लिए 64 बिट आउटपुट इतना अनपेक्षित हो सकता है !!

ज़ुदज़िक का कार्य :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
A >= B ? A * A + A + B : A + B * B;

(-32768, -32768) => 4294967295 जो अहस्ताक्षरित सीमा के लिए 32 बिट या हस्ताक्षरित सीमा के लिए 64 बिट है, लेकिन फिर भी बेहतर है।

अब यह सब जबकि आउटपुट हमेशा सकारात्मक रहा है। हस्ताक्षरित दुनिया में, यह और भी अधिक स्थान की बचत होगी यदि हम आधे आउटपुट को नकारात्मक अक्ष पर स्थानांतरित कर सकते हैं । आप इसे Szudzik के लिए इस तरह कर सकते हैं:

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
C = (A >= B ? A * A + A + B : A + B * B) / 2;
a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;

(-32768, 32767) => -2147483648

(32767, -32768) => -2147450880

(0, 0) => 0 

(32767, 32767) => 2147418112

(-32768, -32768) => 2147483647

मैं क्या करता हूं: 2इनपुट का एक भार लागू करने और फ़ंक्शन के माध्यम से जाने के बाद, मैं फिर से ouput को दो से विभाजित करता हूं और उनमें से कुछ को गुणा करके नकारात्मक अक्ष पर ले जाता हूं -1

परिणाम देखें, किसी हस्ताक्षरित 16बिट संख्या की सीमा में किसी भी इनपुट के लिए , आउटपुट एक हस्ताक्षरित 32बिट पूर्णांक की सीमा के भीतर है जो शांत है। मुझे यकीन नहीं है कि कैंटर पेयरिंग फंक्शन के लिए उसी तरह से जाना जा सकता है, लेकिन जितना संभव हो उतना कुशल नहीं था। इसके अलावा, कैंटर पेयरिंग फंक्शन में शामिल होने वाले अधिक कैलकुलेशन का अर्थ है, इसका धीमा होना

यहाँ एक C # कार्यान्वयन है।

public static long PerfectlyHashThem(int a, int b)
{
    var A = (ulong)(a >= 0 ? 2 * (long)a : -2 * (long)a - 1);
    var B = (ulong)(b >= 0 ? 2 * (long)b : -2 * (long)b - 1);
    var C = (long)((A >= B ? A * A + A + B : A + B * B) / 2);
    return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}

public static int PerfectlyHashThem(short a, short b)
{
    var A = (uint)(a >= 0 ? 2 * a : -2 * a - 1);
    var B = (uint)(b >= 0 ? 2 * b : -2 * b - 1);
    var C = (int)((A >= B ? A * A + A + B : A + B * B) / 2);
    return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}

चूंकि मध्यवर्ती गणनाएं 2Nहस्ताक्षरित पूर्णांक की सीमाओं को पार कर सकती हैं , इसलिए मैंने 4Nपूर्णांक प्रकार (अंतिम विभाजन द्वारा 2परिणाम वापस लाता है 2N) का उपयोग किया है।

वैकल्पिक समाधान पर मैंने जो लिंक प्रदान किया है वह अंतरिक्ष में हर एक बिंदु का उपयोग करते हुए फ़ंक्शन के एक ग्राफ को दर्शाता है। यह देखने के लिए आश्चर्यजनक है कि आप विशिष्ट रूप से एक ही संख्या में निर्देशांक की एक जोड़ी को उलट सकते हैं! नंबरों की जादुई दुनिया !!


5
हस्ताक्षरित पूर्णांकों के लिए संशोधित अनहैश फ़ंक्शन क्या होगा?
पीटलिस

7
यह उत्तर मुझे भ्रमित करता है। यदि आप किसी एकल संख्या के (0,0)माध्यम से मैप करना चाहते हैं (65535,65535), तो a<<16 + bमूल रूप से हर तरह से बेहतर है (तेज, सरल, समझने में आसान, अधिक स्पष्ट) । यदि आप चाहते हैं (-32768,-32768)करने के लिए (327687,327687)के बजाय, बस विषय 32768 पहले।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

2
@ BlueRaja-DannyPflughoeft आप सही हैं। मेरा जवाब मान्य होगा यदि सीमा सीमित या अज्ञात नहीं है। मैं इसे अपडेट करूंगा। मेरे लिए सीमा से पहले मैंने इसे लिखा था। इस उत्तर का संपादन लंबे समय से मेरे दिमाग में है। मुझे जल्द ही कुछ समय मिल जाएगा।
नवफाल

क्या ज़ुदज़िक का कार्य संयोजन या क्रमपरिवर्तन के लिए काम करता है। यह क्रमपरिवर्तन लगता है? यदि मैं संयोजन के लिए उपयोग करना चाहता हूं तो क्या मैं एल्गोरिथ्म के IF और Else भागों को समाप्त कर सकता हूं?
जेमी मार्शल

यहाँ किसी भी लम्बाई के tuples के लिए सामान्यीकृत स्यूदज़िक के कार्य का एक पायथन कार्यान्वयन है: gitlab.com/snippets/32559
डॉक्टर J

47

यदि ए और बी को 2 बाइट्स के साथ व्यक्त किया जा सकता है, तो आप उन्हें 4 बाइट्स पर जोड़ सकते हैं। सबसे महत्वपूर्ण आधे पर ए और सबसे महत्वपूर्ण आधे पर बी रखें।

C भाषा में यह देता है (साइज़ोफ़ (छोटा) = 2 और साइज़ोफ़ (int) = 4) मानते हुए):

int combine(short A, short B)
{
    return A<<16 | B;
}

short getA(int C)
{
    return C>>16;
}

short getB(int C)
{
    return C & 0xFFFF;
}

3
combine()चाहिए return (unsigned short)(A<<16) | (unsigned short)(B); ताकि नकारात्मक संख्याओं को ठीक से पैक किया जा सके।
एंडी

2
@ A<<16और सीमा से बाहर चला जाएगा। यह होना चाहिएreturn (unsigned int)(A<<16) | (unsigned short)(B);
DanSkeel

15

क्या यह भी संभव है?
आप दो पूर्णांकों को मिला रहे हैं। इन दोनों की रेंज -2,147,483,648 से 2,147,483,647 है, लेकिन आप केवल सकारात्मकता लेंगे। यह 2147483647 ^ 2 = 4,61169E + 18 संयोजन बनाता है। चूँकि प्रत्येक संयोजन अद्वितीय होता है और पूर्णांक में परिणाम होता है, इसलिए आपको किसी प्रकार के जादुई पूर्णांक की आवश्यकता होगी जिसमें इस संख्या को शामिल किया जा सके।

या मेरा तर्क त्रुटिपूर्ण है?


+1 यह वही है जो मैं भी सोचता हूं (हालांकि मैंने ए और बी के आदेश की गणना करते हुए कहा था)
एलसी।

4
हाँ आपका तर्क कबूतर सिद्धांत द्वारा सही है। यदि पूर्णांक बाउंड किया गया है या नहीं, तो दुर्भाग्य से पूछने वाले ने यह निर्दिष्ट नहीं किया।
अज्ञात

हां, मैंने इसके बाद भी सोचा था, लेकिन मुझे लगा कि संदेश समान है, इसलिए मैंने पुनर्गणना को परेशान नहीं किया।
बोरिस

इसके अलावा मुझे सिर्फ एहसास हुआ कि मुझे अपना मौका गणना (डच से शाब्दिक अनुवाद) पाठ्यपुस्तकों को फिर से चुनना चाहिए।
बोरिस

2
@ बोरिस: कांस्रेकेनिंग "संभावना सिद्धांत" है।
Stephan202

8

सकारात्मक पूर्णांक के लिए मानक गणितीय तरीका अभाज्य कारक की विशिष्टता का उपयोग करना है।

f( x, y ) -> 2^x * 3^y

नकारात्मक पक्ष यह है कि छवि पूर्णांक की एक बड़ी सीमा तक फैल जाती है, इसलिए जब कंप्यूटर एल्गोरिथ्म में मानचित्रण को व्यक्त करने की बात आती है, तो आपके पास परिणाम के लिए एक उपयुक्त प्रकार चुनने के साथ समस्या हो सकती है।

आप इसे नकारात्मक से निपटने के लिए xऔर y5 और 7 शब्दों की शक्तियों के साथ एक झंडे को एन्कोडिंग करके संशोधित कर सकते हैं।

जैसे

f( x, y ) -> 2^|x| * 3^|y| * 5^(x<0) * 7^(y<0)

गणित ठीक है। लेकिन, जैसा कि बोरिस कहते हैं, यदि आप इसे कंप्यूटर प्रोग्राम के रूप में चलाना चाहते हैं, तो आपको मशीन की बारीकियों को ध्यान में रखना होगा। एल्गोरिथ्म संबंधित मशीन में प्रतिनिधित्व योग्य पूर्णांक के सबसेट के लिए सही ढंग से काम करेगा।
युवल एफ

2
मैंने अपने दूसरे पैराग्राफ में यह बताया। प्रश्न पर टैग 'एल्गोरिथ्म', 'गणितीय' और 'निर्धारक' का संकेत देते हैं, किसी विशेष भाषा का नहीं। इनपुट सीमा सीमित नहीं हो सकती है और पर्यावरण के पास एक अनबाउंड पूर्णांक प्रकार 'bigint' हो सकता है।
सीबी बेली

8

नंबर aपहले, bदूसरा हो। आज्ञा देना pहो a+1वें अभाज्य संख्या, qहो b+1वें अभाज्य संख्या

फिर, परिणाम है pq, अगर a<b,या 2pqअगर a>b। यदि a=b, इसे रहने दें p^2


4
मुझे संदेह है कि आप एक एनपी समाधान चाहते हैं।
user44242

1
क्या यह = 5, b = 14 और a = 6, b = 15 के लिए समान परिणाम नहीं देता है?
लेवेन कीर्सेमेकर्स

3
दो अलग-अलग primes के दो उत्पादों का परिणाम समान नहीं हो सकता है (अद्वितीय मुख्य कारक अपघटन) a = 5, b = 14 -> परिणाम 13 * 47 = 611 a = 6, b = 15 -> परिणाम 17 * 53 = है 901
एस्क

4

मैपिंग बनाना कठिन नहीं है:

   1 2 3 4 5 इस मैपिंग का उपयोग करें यदि (a, b)! = (B, a)
1 0 1 3 6 10
२ २ ४ 16 ११ १६
३ ५ 23 १२ १ 5 २३
4 9 13 18 24 31
५ १४ १ ९ २५ ३२ ४०

   1 2 3 4 5 इस मैपिंग का उपयोग करें यदि (ए, बी) == (बी, ए) (दर्पण)
1 0 1 2 4 6
2 1 3 5 7 10
3 2 5 8 11 14
4 4 8 11 15 19
५ ६ १० १४ १ ९ २४


    0 1 -1 2 -2 यदि आपको नकारात्मक / सकारात्मक की आवश्यकता है तो इसका उपयोग करें
 0 0 1 2 4 6
 1 1 3 5 7 10
-1 2 5 8 11 14
 2 4 8 11 15 19
-2 6 10 14 19 24

यह पता लगाना कि किस तरह से मनमानी ए, बी के लिए मूल्य प्राप्त करना थोड़ा मुश्किल है।


4

f(a, b) = s(a+b) + a, कहाँ पे s(n) = n*(n+1)/2

  • यह एक फ़ंक्शन है - यह नियतात्मक है।
  • यह भी इंजेक्शन है - एफ अलग (ए, बी) जोड़े के लिए विभिन्न मूल्यों को मैप करता है। आप इस तथ्य का उपयोग करके यह साबित कर सकते हैं s(a+b+1)-s(a+b) = a+b+1 < a:।
  • यह काफी छोटे मान लौटाता है - अच्छा है अगर आप इसे सरणी अनुक्रमण के लिए उपयोग करने जा रहे हैं, क्योंकि सरणी का बड़ा होना जरूरी नहीं है।
  • यह कैश-फ्रेंडली है - अगर दो (ए, बी) जोड़े एक-दूसरे के करीब हैं, तो उनके लिए एफ मैप्स नंबर दें, जो एक-दूसरे के करीब हों (अन्य तरीकों की तुलना में)।

मुझे समझ में नहीं आया कि आपका क्या मतलब है:

हमेशा पूर्णांक के धनात्मक या ऋणात्मक पक्ष पर पूर्णांक बनाना चाहिए

मैं इस फ़ोरम में अक्षर (से बड़ा), (कम) कैसे लिख सकता हूं?


2
पात्रों की तुलना में अधिक से अधिक और भीतर से ठीक काम करना चाहिए backtick escapes
TRIG

यह कैंटर पेयरिंग फंक्शन के बराबर है, और जैसे कि नेगेटिव पूर्णांकों के साथ काम नहीं करता है।
जोसफोविक

4

यद्यपि Stephan202 का उत्तर एकमात्र सही मायने में सामान्य है, एक पूर्ण सीमा में पूर्णांक के लिए आप बेहतर कर सकते हैं। उदाहरण के लिए, यदि आपकी सीमा 0..10,000 है, तो आप यह कर सकते हैं:

#define RANGE_MIN 0
#define RANGE_MAX 10000

unsigned int merge(unsigned int x, unsigned int y)
{
    return (x * (RANGE_MAX - RANGE_MIN + 1)) + y;
}

void split(unsigned int v, unsigned int &x, unsigned int &y)
{
    x = RANGE_MIN + (v / (RANGE_MAX - RANGE_MIN + 1));
    y = RANGE_MIN + (v % (RANGE_MAX - RANGE_MIN + 1));
}

पूर्णांक प्रकार के कार्डिनलिटी के वर्गमूल तक की सीमा के लिए परिणाम एकल पूर्णांक में फिट हो सकते हैं। यह Stephan202 की अधिक सामान्य विधि की तुलना में थोड़ा अधिक कुशलता से पैक करता है। इसे डिकोड करना भी काफी सरल है; शुरुआत के लिए कोई वर्गमूल की आवश्यकता नहीं है :)


क्या यह किसी भी तरह से संभव है?
लुकास

4

तर्क के रूप में सकारात्मक पूर्णांकों के लिए और जहां तर्क क्रम मायने नहीं रखता है:

  1. यहाँ एक अनियंत्रित युग्मन क्रिया है :

    <x, y> = x * y + trunc((|x - y| - 1)^2 / 4) = <y, x>
    
  2. X pair y के लिए, यहां एक अद्वितीय अनियंत्रित युग्मन फ़ंक्शन है :

    <x, y> = if x < y:
               x * (y - 1) + trunc((y - x - 2)^2 / 4)
             if x > y:
               (x - 1) * y + trunc((x - y - 2)^2 / 4)
           = <y, x>
    

3

इसे देखें: http://en.wikipedia.org/wiki/Pigeonhole_principle । यदि A, B और C एक ही प्रकार के हैं, तो ऐसा नहीं किया जा सकता है। यदि ए और बी 16-बिट पूर्णांक हैं, और सी 32-बिट है, तो आप बस स्थानांतरण का उपयोग कर सकते हैं।

हैशिंग एल्गोरिदम की प्रकृति यह है कि वे प्रत्येक अलग इनपुट के लिए एक अद्वितीय हैश प्रदान नहीं कर सकते हैं।


2

यहां @nawfal द्वारा दी गई विधि के आधार पर अनबाउंड पूर्णांकों के लिए @DoctorJ के कोड का विस्तार है। यह सांकेतिक शब्दों में बदलना और डिकोड कर सकता है। यह सामान्य सरणियों और सुन्न सरणियों के साथ काम करता है।

#!/usr/bin/env python
from numbers import Integral    

def tuple_to_int(tup):
    """:Return: the unique non-negative integer encoding of a tuple of non-negative integers."""
    if len(tup) == 0:  # normally do if not tup, but doesn't work with np
        raise ValueError('Cannot encode empty tuple')
    if len(tup) == 1:
        x = tup[0]
        if not isinstance(x, Integral):
            raise ValueError('Can only encode integers')
        return x
    elif len(tup) == 2:
        # print("len=2")
        x, y = tuple_to_int(tup[0:1]), tuple_to_int(tup[1:2])  # Just to validate x and y

        X = 2 * x if x >= 0 else -2 * x - 1  # map x to positive integers
        Y = 2 * y if y >= 0 else -2 * y - 1  # map y to positive integers
        Z = (X * X + X + Y) if X >= Y else (X + Y * Y)  # encode

        # Map evens onto positives
        if (x >= 0 and y >= 0):
            return Z // 2
        elif (x < 0 and y >= 0 and X >= Y):
            return Z // 2
        elif (x < 0 and y < 0 and X < Y):
            return Z // 2
        # Map odds onto negative
        else:
            return (-Z - 1) // 2
    else:
        return tuple_to_int((tuple_to_int(tup[:2]),) + tuple(tup[2:]))  # ***speed up tuple(tup[2:])?***


def int_to_tuple(num, size=2):
    """:Return: the unique tuple of length `size` that encodes to `num`."""
    if not isinstance(num, Integral):
        raise ValueError('Can only encode integers (got {})'.format(num))
    if not isinstance(size, Integral) or size < 1:
        raise ValueError('Tuple is the wrong size ({})'.format(size))
    if size == 1:
        return (num,)
    elif size == 2:

        # Mapping onto positive integers
        Z = -2 * num - 1 if num < 0 else 2 * num

        # Reversing Pairing
        s = isqrt(Z)
        if Z - s * s < s:
            X, Y = Z - s * s, s
        else:
            X, Y = s, Z - s * s - s

        # Undoing mappint to positive integers
        x = (X + 1) // -2 if X % 2 else X // 2  # True if X not divisible by 2
        y = (Y + 1) // -2 if Y % 2 else Y // 2  # True if Y not divisible by 2

        return x, y

    else:
        x, y = int_to_tuple(num, 2)
        return int_to_tuple(x, size - 1) + (y,)


def isqrt(n):
    """":Return: the largest integer x for which x * x does not exceed n."""
    # Newton's method, via http://stackoverflow.com/a/15391420
    x = n
    y = (x + 1) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

2

कैसे कुछ सरल के बारे में: दो संख्याओं को देखते हुए, ए और बी को संक्षिप्त होने दें: 'ए' + ';' + 'बी'। फिर आउटपुट हैश (str) होने दें। मुझे पता है कि यह एक गणितीय उत्तर नहीं है, लेकिन एक साधारण अजगर (जिसकी अंतर्निहित हैश फ़ंक्शन में है) स्क्रिप्ट को काम करना चाहिए।


2
लेकिन (are,११) और (1१,१) को एक ही नंबर to११ से मैप किया गया है
लीवी एल

यह एक अच्छी बात है। आप केवल बीच में एक प्रतीक जोड़कर उस मुद्दे को ठीक कर सकते हैं। तो (8, 11) हैश के लिए स्ट्रिंग "8-11" और (81, 1) हैश के लिए स्ट्रिंग "81-1" है। तो (ए, बी) के लिए सामान्य रूप से स्ट्रिंग "एबी" हैश। (मुझे पता है कि यह हैकिंग लगता है, लेकिन यह काम करना चाहिए)।
माधव नकर

यह भी गलत है क्योंकि यह कार्य दो पूर्णांकों को एक नए पूर्णांक में मैप करना है, न कि एक प्रतीक के साथ एक स्ट्रिंग
लीवी एल

मैं गणितीय दृष्टिकोण के बजाय सीएस के दृष्टिकोण से आ रहा हूं (गणितीय समाधानों के लिए उपरोक्त प्रतिक्रियाओं को देखें)। मैं दो पूर्णांक ले रहा हूं, उन्हें एक स्ट्रिंग में बना रहा हूं, जब तब एक पूर्णांक में बदल जाता है। अनिवार्य रूप से, हाँ, मैं दो पूर्णांकों को नए सिरे से मैप कर रहा हूं।
माधव नकर

1

आप जो सुझाव देते हैं वह असंभव है। आप हमेशा टकराव होगा।

दो वस्तुओं को दूसरे एकल सेट में मैप करने के लिए, मैप किए गए सेट में अपेक्षित संयोजनों की संख्या का न्यूनतम आकार होना चाहिए:

32-बिट पूर्णांक मानते हुए, आपके पास 2147483647 धनात्मक पूर्णांक हैं। इनमें से दो को चुनना जहां ऑर्डर मायने नहीं रखता है और पुनरावृत्ति के साथ 2305843008139952128 संयोजन प्राप्त होता है। यह 32-बिट पूर्णांक के सेट में अच्छी तरह से फिट नहीं है।

हालाँकि आप इस मैपिंग को 61 बिट्स में फिट कर सकते हैं। 64-बिट पूर्णांक का उपयोग करना शायद सबसे आसान है। उच्च शब्द को छोटे पूर्णांक और निम्न शब्द को बड़े पर सेट करें।


1

मान लें कि आपके पास 32 बिट पूर्णांक है, तो पहले A को 16 बिट आधे में और B को दूसरे में क्यों नहीं स्थानांतरित करें?

def vec_pack(vec):
    return vec[0] + vec[1] * 65536;


def vec_unpack(number):
    return [number % 65536, number // 65536];

यह संभव के रूप में अंतरिक्ष के रूप में कुशल और गणना करने के लिए सस्ता होने के अलावा, वास्तव में एक शांत साइड इफेक्ट यह है कि आप पैक्ड नंबर पर वेक्टर गणित कर सकते हैं।

a = vec_pack([2,4])
b = vec_pack([1,2])

print(vec_unpack(a+b)) # [3, 6] Vector addition
print(vec_unpack(a-b)) # [1, 2] Vector subtraction
print(vec_unpack(a*2)) # [4, 8] Scalar multiplication

0

हमारे पास दो नंबर B और C हैं, उन्हें एक नंबर A में एन्कोडिंग करें

ए = बी + सी * एन

कहाँ पे

बी = ए% एन = बी

सी = ए / एन = सी


2
इस प्रतिनिधित्व को अद्वितीय बनाने के लिए आप N को कैसे चुनते हैं? यदि आप उस समस्या को हल करते हैं, तो यह उत्तर ऊपर के लोगों से अलग कैसे है?
प्रून

आपको यह जोड़ना चाहिए कि N, B और C. दोनों से बड़ा होना चाहिए
Radoslav Stoyanov

0

सकारात्मक पूर्णांक A और B को देखते हुए, D के पास D = अंकों की संख्या है, और E = अंकों की संख्या B है। परिणाम D, 0, E, 0, A, और B का एक संयोजन हो सकता है।

उदाहरण: A = 300, B = 12. D = 3, E = 2 परिणाम = 302030012। यह इस तथ्य का लाभ उठाता है कि एकमात्र संख्या जो 0 से शुरू होती है, 0 है,

प्रो: सांकेतिक शब्दों में बदलना आसान, डिकोड करने में आसान, मानव पठनीय, महत्वपूर्ण अंकों की तुलना सबसे पहले की जा सकती है, गणना के बिना तुलना करने की क्षमता, सरल त्रुटि जाँच।

विपक्ष: परिणामों का आकार एक मुद्दा है। लेकिन यह ठीक है, हम किसी भी कंप्यूटर में अनबाउंड पूर्णांक क्यों संग्रहीत कर रहे हैं।


0

यदि आप अधिक नियंत्रण चाहते हैं जैसे कि पहले नंबर के लिए X बिट्स आवंटित करें और दूसरे नंबर के लिए Y बिट्स, तो आप इस कोड का उपयोग कर सकते हैं:

class NumsCombiner
{

    int num_a_bits_size;
    int num_b_bits_size;

    int BitsExtract(int number, int k, int p)
    {
        return (((1 << k) - 1) & (number >> (p - 1)));
    }

public:
    NumsCombiner(int num_a_bits_size, int num_b_bits_size)
    {
        this->num_a_bits_size = num_a_bits_size;
        this->num_b_bits_size = num_b_bits_size;
    }

    int StoreAB(int num_a, int num_b)
    {
        return (num_b << num_a_bits_size) | num_a;
    }

    int GetNumA(int bnum)
    {
        return BitsExtract(bnum, num_a_bits_size, 1);
    }

    int GetNumB(int bnum)
    {
        return BitsExtract(bnum, num_b_bits_size, num_a_bits_size + 1);
    }
};

मैं कुल में 32 बिट्स का उपयोग करता हूं। यहाँ विचार यह है कि यदि आप उदाहरण के लिए चाहते हैं कि पहली संख्या 10 बिट्स तक होगी और दूसरी संख्या 12 बिट्स तक होगी, तो आप यह कर सकते हैं:

NumsCombiner nums_mapper(10/*bits for first number*/, 12/*bits for second number*/);

अब आप num_aउस अधिकतम संख्या में स्टोर कर सकते हैं जो कि 2^10 - 1 = 1023और अधिकतम num_bमूल्य में है 2^12 - 1 = 4095

संख्या A और संख्या B के लिए मान सेट करने के लिए:

int bnum = nums_mapper.StoreAB(10/*value for a*/, 12 /*value from b*/);

अब bnumसभी बिट्स (कुल में 32 बिट्स हैं। आप 64 बिट्स का उपयोग करने के लिए कोड को संशोधित कर सकते हैं) संख्या को प्राप्त करने के लिए:

int a = nums_mapper.GetNumA(bnum);

संख्या बी पाने के लिए:

int b = nums_mapper.GetNumB(bnum);

EDIT: bnumवर्ग के अंदर संग्रहीत किया जा सकता है। मैंने ऐसा नहीं किया क्योंकि मेरी अपनी जरूरतों को मैंने कोड साझा किया और आशा है कि यह मददगार होगी।

स्रोत के लिए धन्यवाद: https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ फ़ंक्शन के लिए बिट निकालने के लिए और mouvicielइस पोस्ट में उत्तर देने के लिए धन्यवाद भी । इन स्रोतों का उपयोग करके मैं अधिक उन्नत समाधान का पता लगा सकता हूं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.