একটিতে দুটি পূর্ণসংখ্যার ম্যাপিং, অনন্য এবং নির্বিচারে উপায়ে


235

দুটি এবং ইতিবাচক পূর্ণসংখ্যার ক এবং বি কল্পনা করুন আমি এই দুটিকে একটি একক পূর্ণসংখ্যার সিতে সংযুক্ত করতে চাই

ডি এবং ই এর সাথে সংযুক্ত অন্য কোনও পূর্ণসংখ্যা থাকতে পারে না সুতরাং এগুলি সংযোজন অপারেটরের সাথে সংযুক্তি কার্যকর হয় না। উদাহরণস্বরূপ 30 + 10 = 40 = 40 + 0 = 39 + 1 উভয়ই মিলিত কাজ করে না। যেমন "31" + "2" = 312 = "3" + "12"

এই সংমিশ্রণ ক্রিয়াকলাপটিও নির্বিচারে হওয়া উচিত (সর্বদা একই ফলাফল একই ইনপুটগুলির সাথে পাওয়া যায়) এবং সর্বদা পূর্ণসংখ্যার ধনাত্মক বা নেতিবাচক দিক থেকে একটি পূর্ণসংখ্যা পাওয়া উচিত।


10
আপনার যদি সফ্টওয়্যারটিতে পূর্ণসংখ্যার অর্থ বা গণিতে পূর্ণসংখ্যার অর্থ হয় তবে আপনাকে স্পষ্ট করা উচিত। সফ্টওয়্যারটিতে, আপনি কোনও পূর্ণসংখ্যার ধরণের বাছাই করেন এবং এটির আকার হবে, সুতরাং আপনার একটি সীমাবদ্ধ সংখ্যা রয়েছে, সুতরাং এর কোনও সমাধান নেই (অবশ্যই, যদি না আপনার ইনপুট ডেটা কিছু পরিসরের মধ্যে থাকে এবং আপনার আউটপুট হতে পারে যেকোন পূর্ণসংখ্যা)। গণিতে এসকের সমাধান দেখুন।
ড্যানিয়েল দারানাস

আমি একটি স্বল্প, ধনাত্মক ব্যাপ্তিতে সীমাবদ্ধ পূর্ণসংখ্যার কথা বলছি। 0 থেকে 10,000 বলুন
ক্ষতি করুন

27
@ হার্ম: ঠিক কীভাবে 10,001*A + B?
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

2
আমি এই পিএইচপি ফাংশনগুলি পেয়েছি: gist.github.com/hannesl/8031402
কাকান

যদি অর্ডারটি গুরুত্ব না দেয় যেমন: (3,12) এবং (12,3) একই ফলাফল দেয়, আমি "A + B" + "A * B" ব্যবহার করি
সডজ

উত্তর:


233

আপনি বাইজিক NxN -> Nম্যাপিংয়ের সন্ধান করছেন। এগুলি উদাহরণস্বরূপ ডোভেটেলিংয়ের জন্য ব্যবহৃত হয় । তথাকথিত জোড় কার্যকারিতা পরিচিতির জন্য এই পিডিএফটি দেখুন । উইকিপিডিয়া একটি নির্দিষ্ট জুটিবদ্ধকরণের সূচনা করে, যার নাম ক্যান্টোর জুড়ি ফাংশন :

পাই (কে 1, কে 2) = 1/2 (কে 1 + কে 2) (কে 1 + কে 2 + 1) + কে 2

তিনটি মন্তব্য:

  • অন্যরা যেমন পরিষ্কার করে দিয়েছে, আপনি যদি একটি জুড়ি ফাংশন বাস্তবায়নের পরিকল্পনা করেন তবে শীঘ্রই আপনি নির্বিচারে বড় ইন্টিজার (বিগনামস) পেতে পারেন।
  • আপনি যদি জোড়া (ক, খ) এবং (খ, ক) এর মধ্যে পার্থক্য তৈরি করতে না চান, তবে জোড় কার্যটি প্রয়োগ করার আগে a এবং b কে বাছাই করুন।
  • আসলে আমি মিথ্যা বললাম। আপনি বাইজিক ZxZ -> Nম্যাপিংয়ের সন্ধান করছেন। ক্যান্টারের ফাংশনটি কেবল অ-নেতিবাচক সংখ্যাগুলিতে কাজ করে। এটি অবশ্য কোনও সমস্যা নয়, কারণ এটি f : Z -> Nযেমন একটি বাইজিকেশন সংজ্ঞায়িত করা সহজ :
    • f (n) = n * 2 যদি এন> = 0 হয়
    • f (n) = -n * 2 - 1 যদি এন <0 হয়

13
+1 আমি মনে করি এটি সীমাহীন পূর্ণসংখ্যার সঠিক উত্তর।
অজানা

4
আমি কীভাবে আবার কে 1, কে 2 এর মান পেতে পারি?
মিনুমাস্টার

3
@ মিনুমাস্টার: এটি একই উইকিপিডিয়া নিবন্ধে বর্ণিত হয়েছে ক্যান্টর জুটি ফাংশনটি ইনভার্টিংয়ের আওতায় ।
স্টিফান202

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) ম্যাপিং 8585803520 হবে যা আপনি দেখতে পাচ্ছেন 32 বিটের মধ্যে মাপসই করা যাবে না।

সুজডজিকের কার্য লিখুন :

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 যা ইন্টার 64। 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 বিট, তবে আরও ভাল।

এখন এই সমস্ত যখন আউটপুট সর্বদা ইতিবাচক ছিল। স্বাক্ষরিত বিশ্বে এটি অর্ধেক আউটপুটটিকে নেতিবাচক অক্ষরে স্থানান্তর করতে পারলে আরও বেশি স্থান সাশ্রয় হবে । আপনি সুজডজিকের জন্য এটি এটি করতে পারেন:

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ইনপুটগুলিতে একটি ওজন প্রয়োগ করার পরে এবং ফাংশনটি দিয়ে যাওয়ার পরে, আমি তারপরে আউটপুটটিকে দুটি দ্বারা বিভক্ত করি এবং তাদের কয়েকটিকে গুণিত করে নেতিবাচক অক্ষে নিয়ে যাই -1

ফলাফল দেখুন, একটি স্বাক্ষরিত 16বিট সংখ্যার পরিসরের কোনও ইনপুটের জন্য আউটপুট একটি স্বাক্ষরিত 32বিট পূর্ণসংখ্যার সীমাতে থাকে যা দুর্দান্ত। ক্যান্টোর জুড়ি ফাংশনটির জন্য একই পদ্ধতিতে কীভাবে যাবেন আমি নিশ্চিত নই তবে এটি যতটা দক্ষ তা ততটা চেষ্টা করিনি। তদ্ব্যতীত, ক্যান্টর জুটিবদ্ধকরণের কার্যক্রমে জড়িত আরও গণনার অর্থ এটি খুব ধীর

এখানে একটি সি # বাস্তবায়ন রয়েছে।

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
@ ব্লুরাজা-ড্যানি ফ্লুঘুফুট আপনি ঠিক বলেছেন। আমার উত্তর বৈধ হবে যদি পরিসীমা সীমাবদ্ধ বা অজানা নয়। আমি এটি আপডেট করব। আমার কাছে সীমাবদ্ধতার আগে আমি এটি লিখেছিলাম। এই উত্তরটি সম্পাদনা করা আমার মনে দীর্ঘকাল ধরে। আমি শীঘ্রই কিছু সময় খুঁজে পেতে হবে।
নওফাল

স্জডজিকের কার্যকারিতা কি সংমিশ্রণ বা ক্রমানুসারে কাজ করে? মনে হচ্ছে ঠিক কি অনুমতি দেওয়া হচ্ছে? আমি যদি কম্বিনেশনের জন্য ব্যবহার করতে চাই তবে আমি কি কেবল অ্যালগরিদমের আইএফ এবং অন্য অংশগুলি মুছে ফেলতে পারি?
জেমি মার্শাল

এখানে যে কোনও দৈর্ঘ্যের দ্বিগুণগুলিতে
ডাক্তার জে

47

যদি A এবং B 2 বাইট দিয়ে প্রকাশ করা যায় তবে আপনি সেগুলি 4 বাইটে সংযুক্ত করতে পারেন। একটি সবচেয়ে গুরুত্বপূর্ণ অর্ধেক এবং বি কমপক্ষে উল্লেখযোগ্য অর্ধেক রাখুন।

সি ভাষায় এটি দেয় (আকার ধরে (সংক্ষিপ্ত) = 2 এবং মাপ (পূর্ববর্তী) = 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);
ড্যানস্কিল

15

এটা কি সম্ভব?
আপনি দুটি পূর্ণসংখ্যার সমন্বয় করছেন। তাদের উভয়েরই -2,147,483,648 থেকে 2,147,483,647 পরিসীমা রয়েছে তবে আপনি কেবল ইতিবাচক পদক্ষেপ নেবেন। এটি 2147483647 ^ 2 = 4,61169E + 18 টি সমন্বয় করে। যেহেতু প্রতিটি সংমিশ্রণটি অনন্য হতে হবে এবং পূর্ণসংখ্যার ফলস্বরূপ, আপনার একরকম জাদুকর পূর্ণসংখ্যার প্রয়োজন হবে যা এই পরিমাণে সংখ্যায় থাকতে পারে।

নাকি আমার যুক্তি ত্রুটিযুক্ত?


+1 এটি আমিও তাই মনে করি (যদিও আমি হিসাবটি ক এবং খ এর ক্রম বলার অপেক্ষা রাখে না)
এলসি।

4
হ্যাঁ আপনার যুক্তি কবুতরের নীতি দ্বারা সঠিক। দুর্ভাগ্যক্রমে প্রশ্নকর্তা পূর্ণসংখ্যাটি আবদ্ধ কিনা তা নির্দিষ্ট করে নি।
অজানা

হ্যাঁ, আমারও এটি ছিল পরবর্তী চিন্তাভাবনা, তবে আমি ভেবেছিলাম যে বার্তাটি মূলত একই, তাই আমি পুনরুক্তি করতে বিরত হই নি।
বরিস কলেনস

এছাড়াও আমি ঠিক বুঝতে পারি আমার সুযোগের গণনা (ডাচ থেকে আক্ষরিক অনুবাদ) পাঠ্যপুস্তকগুলি আবার নেওয়া উচিত।
বরিস কলেনস

2
@ বোরিস: কানসেকেনিং হচ্ছে "সম্ভাব্যতা তত্ত্ব"।
স্টেফান202

8

ধনাত্মক পূর্ণসংখ্যার জন্য স্ট্যান্ডার্ড গাণিতিক উপায় হ'ল প্রধান গুণককরণের স্বতন্ত্রতা ব্যবহার করা iqu

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

নেতিবাচকতাটি হ'ল চিত্রটি একটি বৃহত পরিসরের সংখ্যা বিস্তৃত করে যখন কম্পিউটার অ্যালগরিদমে ম্যাপিং প্রকাশ করার কথা আসে তখন ফলাফলের জন্য উপযুক্ত ধরণের চয়ন করার ক্ষেত্রে আপনার সমস্যা হতে পারে।

নেতিবাচক মোকাবেলা করতে xএবং y5 এবং 7 পদগুলির ক্ষমতা সহ একটি পতাকা এনকোড করে আপনি এটি সংশোধন করতে পারেন ।

যেমন

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

গণিত ঠিক আছে। তবে, যেমন বরিস বলেছেন, আপনি যদি এটি কম্পিউটার প্রোগ্রাম হিসাবে চালাতে চান তবে আপনাকে মেশিনের সুনির্দিষ্টতা বিবেচনায় নিতে হবে। অ্যালগরিদম সম্পর্কিত মেশিনে উপস্থাপনযোগ্য পূর্ণসংখ্যার একটি উপসেটের জন্য সঠিকভাবে কাজ করবে।
ইউভাল এফ

2
আমি আমার দ্বিতীয় অনুচ্ছেদে এটি বর্ণনা করেছি। প্রশ্নের ট্যাগগুলি কোনও নির্দিষ্ট ভাষা নয়, 'অ্যালগোরিদম', 'গাণিতিক' এবং 'নির্বিচারক' নির্দেশ করে। ইনপুট পরিসরটি সীমাবদ্ধ নাও হতে পারে এবং পরিবেশের একটি আনবাউন্ডেড পূর্ণসংখ্যার ধরণ 'বিগিন্ট' থাকতে পারে।
সিবি বেইলি

8

সংখ্যাটি aপ্রথম, bদ্বিতীয় হওয়া যাক । দিন pহতে a+1-th মৌলিক সংখ্যা, qহতে b+1-th মৌলিক সংখ্যা

তারপরে, ফলাফলটি হয় pq, যদি a<b,বা 2pqহয় a>b। যদি a=b, এটি হতে দিন p^2


4
আমি সন্দেহ করি যে আপনি এনপি সমাধান চান।
ব্যবহারকারী 44242

1
এটি কি এক = 5, বি = 14 এবং a = 6, বি = 15 এর জন্য একই ফলাফল তৈরি করে না?
লিভেন কের্মসেকারগণ

3
দুটি পৃথক প্রাইমের দুটি পণ্য একই ফলাফল (অনন্য প্রাইম ফ্যাক্টর পচন) এক = 5, খ = 14 -> ফলাফল 13 * 47 = 611 এ = 6, বি = 15 -> ফলাফল 17 * 53 = 901
এএসকে

4

ম্যাপিংটি তৈরি করা এতটা কঠিন নয়:

   1 (3, 5) এই মানচিত্রটি ব্যবহার করুন যদি (ক, খ)! = (খ, ক)
1 0 1 3 6 10
2 2 4 7 11 16
3 5 8 12 17 23
4 9 13 18 24 31
5 14 19 25 32 40

   1 2 3 4 5 এই মানচিত্রটি ব্যবহার করুন যদি (a, b) == (খ, ক) (আয়না)
1 0 1 2 4 6
2 1 3 5 7 10
3 2 5 8 11 14
4 4 8 11 15 19
5 6 10 14 19 24


    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
  • এটি বেশ ছোট মানগুলি ফেরায় - ভাল যদি আপনার এটি অ্যারে সূচকের জন্য ব্যবহার করতে চলেছে, কারণ অ্যারে বড় হওয়ার দরকার নেই।
  • এটি ক্যাশে-বান্ধব - যদি দুটি (ক, খ) জোড়া একে অপরের কাছাকাছি থাকে, তবে চ এগুলি সংখ্যার মানচিত্র যা একে অপরের নিকটে থাকে (অন্যান্য পদ্ধতির তুলনায়)।

আপনি কী বলতে চাইছেন তা আমি বুঝতে পারি নি:

ইতিমধ্যে পূর্ণসংখ্যার ধনাত্মক বা onণাত্মক দিকের একটি পূর্ণসংখ্যা পাওয়া উচিত

এই ফোরামে আমি কীভাবে (এর চেয়েও বেশি), (এর চেয়ে কম) অক্ষর লিখতে পারি?


2
অক্ষরের চেয়ে বৃহত্তর এবং এর চেয়ে কমের মধ্যে ভাল কাজ করা উচিত backtick escapes
ট্রিগ

এটি ক্যান্টোর জুড়ি ফাংশনের সমতুল্য এবং যেমনটি নেতিবাচক পূর্ণসংখ্যার সাথে কাজ করে না।
ফেভার জোসিপোভিচ

4

যদিও স্টেফান202 এর উত্তরটি কেবলমাত্র সত্যই সাধারণ, একটি সীমাবদ্ধ পরিসরের পূর্ণসংখ্যার জন্য আপনি আরও ভাল করতে পারেন। উদাহরণস্বরূপ, যদি আপনার পরিসীমা 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));
}

পূর্ণসংখ্যার ধরণের কার্ডিনালিটির বর্গমূল পর্যন্ত পরিসরের জন্য ফলাফলগুলি একটি একক পূর্ণসংখ্যায় ফিট করতে পারে। স্টেফান202 এর আরও সাধারণ পদ্ধতির চেয়ে কিছুটা দক্ষতার সাথে এই প্যাকগুলি প্যাক করে। এটি ডিকোড করাও যথেষ্ট সহজ; প্রারম্ভিকদের জন্য কোনও বর্গাকার শিকড়ের প্রয়োজন নেই :)


এটি কি কোনও সুযোগেই ভাসমানদের পক্ষে সম্ভব?
লুকাস

4

আর্গুমেন্ট হিসাবে ধনাত্মক পূর্ণসংখ্যার জন্য এবং যেখানে আর্গুমেন্ট অর্ডারটি বিবেচনা করে না:

  1. এখানে একটি আনর্ডার্ডযুক্ত জুড়ি ফাংশন রয়েছে :

    <x, y> = x * y + trunc((|x - y| - 1)^2 / 4) = <y, x>
    
  2. এক্স ≠ ওয়াইয়ের জন্য, এখানে একটি অনন্য অর্ডারর্ডার্ড জুড়ি ফাংশন রয়েছে :

    <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.wikedia.org/wiki/Pigeonhole_prصول । যদি এ, বি এবং সি একই ধরণের হয় তবে এটি করা যায় না। যদি A এবং B 16-বিট পূর্ণসংখ্যা হয় এবং সি 32-বিট হয় তবে আপনি কেবল স্থানান্তর ব্যবহার করতে পারেন।

হ্যাশিং অ্যালগরিদমগুলির প্রকৃতি হ'ল তারা প্রতিটি পৃথক ইনপুটগুলির জন্য একটি অনন্য হ্যাশ সরবরাহ করতে পারে না।


2

@ নওফাল দ্বারা প্রদত্ত পদ্ধতির ভিত্তিতে আনবাউন্ডেড পূর্ণসংখ্যায় @ ডক্টর জের কোডটি বাড়ানো হয়েছে। এটি এনকোড এবং ডিকোড করতে পারে। এটি সাধারণ অ্যারে এবং অলস অ্যারেগুলির সাথে কাজ করে।

#!/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

আরও সহজ কিছু সম্পর্কে কীভাবে: দুটি সংখ্যা দেওয়া, এ এবং বি এর সংমিশ্রণ হতে দিন: 'এ' + ';' + 'বি'। তারপরে আউটপুটটি হ্যাশ (স্ট্র) হতে দিন। আমি জানি যে এটি কোনও গাণিতিক উত্তর নয়, তবে একটি সাধারণ অজগর (যা একটি অন্তর্নির্মিত হ্যাশ ফাংশন রয়েছে) স্ক্রিপ্টটির কাজটি করা উচিত।


2
তবে (8,11) এবং (81,1) একই 811 নম্বরে ম্যাপ করা হয়েছে
লিভি এল

এটি একটি ভাল পয়েন্ট। আপনি মাঝখানে একটি চিহ্ন যোগ করে এই সমস্যাটি সমাধান করতে পারেন। সুতরাং (8, 11) হ্যাশ স্ট্রিং "8-11" এবং (81, 1) হ্যাশ স্ট্রিং "81-1" এর জন্য। সুতরাং সাধারণভাবে (এ, বি) হ্যাশ স্ট্রিং "এবি"। (আমি জানি এটি হ্যাকি লাগছে তবে এটি কার্যকর হওয়া উচিত)।
মাধব নাকার

এটিও ভুল কারণ এই কাজটি একটি নতুন পূর্ণসংখ্যার সাথে দুটি পূর্ণসংখ্যার মানচিত্র তৈরি করা, প্রতীক সহ একটি স্ট্রিং নয়
লিভি এল

আমি গাণিতিকের চেয়ে সিএস দৃষ্টিকোণ থেকে আসছি (গাণিতিক সমাধানের জন্য উপরের প্রতিক্রিয়াগুলি দেখুন)। আমি দুটি পূর্ণসংখ্যার গ্রহণ করছি, সেগুলিকে একটি স্ট্রিংয়ে পরিণত করছি, যখন তখন পূর্ণসংখ্যায় পরিণত হয়। মূলত, হ্যাঁ আমি একটি নতুন সাথে দুটি পূর্ণসংখ্যা ম্যাপ করছি।
মাধব নাকার

1

আপনি যা পরামর্শ দেন তা অসম্ভব। আপনার সবসময় সংঘর্ষ হবে।

অন্য একক সেটে দুটি অবজেক্ট ম্যাপ করার জন্য, ম্যাপ করা সেটটিতে প্রত্যাশিত সংমিশ্রণের সংখ্যার নূন্যতম আকার থাকতে হবে:

একটি 32-বিট পূর্ণসংখ্যা ধরে নিলে, আপনার কাছে 2147483647 ইতিবাচক পূর্ণসংখ্যা রয়েছে। এই দুটি যেখানে অর্ডার বিবেচনা করে এবং পুনরাবৃত্তির সাথে মিলবে তা বেছে নেওয়া 2305843008139952128 সংমিশ্রণ দেয়। 32-বিট পূর্ণসংখ্যার সেটটিতে এটি দুর্দান্তভাবে ফিট করে না।

তবে আপনি 61 ​​বিটে এই ম্যাপিংটি ফিট করতে পারেন। একটি 64-বিট পূর্ণসংখ্যার ব্যবহার সম্ভবত সবচেয়ে সহজ। উচ্চতর শব্দটিকে ছোট পূর্ণসংখ্যায় এবং কম শব্দটিকে বৃহত্তর সাথে সেট করুন।


1

বলুন আপনার একটি 32 বিট পূর্ণসংখ্যা রয়েছে, কেন কেবল এটিকে প্রথম 16 বিট অর্ধেক এবং বিটিকে অন্যটিতে স্থানান্তরিত করবেন না?

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

আসুন আমরা দুটি নম্বর বি এবং সি থাকি এবং এগুলিকে একক সংখ্যায় এনকোড করি

এ = বি + সি * এন

কোথায়

বি = এ% এন = বি

সি = এ / এন = সি


2
এই প্রতিনিধিত্বকে অনন্য করতে আপনি কীভাবে এন নির্বাচন করবেন? আপনি যদি এই সমস্যার সমাধান করেন তবে উপরের উত্তরগুলির চেয়ে এই উত্তরটি কীভাবে আলাদা?
খেজুর

আপনার যোগ করা উচিত যে এন অবশ্যই বি এবং সি উভয়ের চেয়ে বড় হতে হবে
রেডোস্লাভ স্টোয়ানভ

0

A এবং B কে ধনাত্মক পূর্ণসংখ্যা দেওয়া হয়েছে, A এর সাথে D = সংখ্যা এবং E = সংখ্যার বি সংখ্যা রয়েছে ফলাফলটি D, 0, E, 0, A, এবং B এর সংমিশ্রণ হতে পারে

উদাহরণ: এ = 300, বি = 12. ডি = 3, ই = 2 ফলাফল = 302030012. এটি 0 টি দিয়ে শুরু হওয়া একমাত্র সংখ্যা 0, এই সত্যটির সুবিধা নেয়

প্রো: এনকোড করা সহজ, ডিকোড করা সহজ, মানব পাঠযোগ্য, উল্লেখযোগ্য অঙ্কগুলির সাথে প্রথম তুলনা করা যেতে পারে, গণনা ছাড়াই তুলনা করার সম্ভাবনা, সাধারণ ত্রুটি পরীক্ষা করা।

কনস: ফলাফলের আকার একটি সমস্যা। তবে এটি ঠিক আছে, কেন আমরা যে কোনও উপায়ে কম্পিউটারে সীমাহীন পূর্ণসংখ্যা সংরক্ষণ করছি।


0

যদি আপনি আরও নিয়ন্ত্রণ চান যেমন প্রথম সংখ্যাটির জন্য এক্স বিট এবং দ্বিতীয় নম্বরটির জন্য ওয়াই বিটস বরাদ্দ করুন তবে আপনি এই কোডটি ব্যবহার করতে পারেন:

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 এবং num 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);

সম্পাদনা: bnumক্লাসের ভিতরে সংরক্ষণ করা যেতে পারে। আমি এটি করিনি কারণ আমার নিজের প্রয়োজনগুলির সাথে আমি কোডটি ভাগ করেছি এবং আশা করি এটি কার্যকর হবে be

উত্সের জন্য ধন্যবাদ: https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ বিট নিষ্কাশন করার জন্য এবং mouvicielএই পোস্টে উত্তর দেওয়ার জন্য ধন্যবাদ । উত্সগুলিতে এগুলি ব্যবহার করে আমি আরও উন্নত সমাধান বের করতে পারি

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.