2011-02-06 28 views
5

मैं एक छोटे से, तेजी से तलाश कर रहा हूँ (दोनों दिशाओं में) पूर्णांकों का निम्न सूची और रेंज 0-127 के एक सबसेट के बीच द्विभाजित मानचित्रण:कुशल मानचित्रण सेट

0x200C, 0x200D, 0x200E, 0x200F, 
0x2013, 0x2014, 0x2015, 0x2017, 
0x2018, 0x2019, 0x201A, 0x201C, 
0x201D, 0x201E, 0x2020, 0x2021, 
0x2022, 0x2026, 0x2030, 0x2039, 
0x203A, 0x20AA, 0x20AB, 0x20AC, 
0x20AF, 0x2116, 0x2122 

एक स्पष्ट समाधान है:

y = x>>2 & 0x40 | x & 0x3f; 
x = 0x2000 | y<<2 & 0x100 | y & 0x3f; 

संपादित करें: मैं मान, विशेष रूप से 0x20Ax है, जो ऊपर साथ काम नहीं करते के कुछ याद आ रही थी।

एक और स्पष्ट समाधान एक लुकअप टेबल है, लेकिन इसे अनावश्यक रूप से बड़ा किए बिना, एक लुकअप टेबल को कुछ भी पुनर्व्यवस्थित की आवश्यकता होगी और मुझे संदेह है कि पूरा कार्य सरल बिट पुनर्संरचना के साथ बेहतर हो सकता है।

उत्सुकता के लिए, उन जादू संख्याएं केवल "बड़े" यूनिकोड कोडपॉइंट हैं जो विरासत आईएसओ -885 9 और विंडोज कोडपेज में दिखाई देती हैं।

+0

http://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm –

+0

btw, एक द्विभाजित मानचित्रण एक सबसेट पर injective कहा जाता है;) इसो-8859- में – Christoph

उत्तर

1

मैं जानता हूँ कि यह बदसूरत है, लेकिन अंतिम मान को छोड़कर अन्य सभी को पहले से ही अनूठा है, तो आपको सबसे कम 6 बिट पर विचार कर रहे हैं, तो आप सिर्फ निर्माण कर सकते हैं और उलटा नक्शा:

int ints[] = {0x200C, 0x200D, 0x200E, 0x200F, 
       0x2013, 0x2014, 0x2015, 0x2017, 
       0x2018, 0x2019, 0x201A, 0x201C, 
       0x201D, 0x201E, 0x2020, 0x2021, 
       0x2022, 0x2026, 0x2030, 0x2039, 
       0x203A, 0x20AA, 0x20AB, 0x20AC, 
       0x20AF, 0x2116, 0x2122}; 

int invmap[64]; 

void mkinvmap() 
{ 
    for (int i=0; i<26; i++) 
     invmap[ints[i]&63] = ints[i]; 
    invmap[0] = 0x2122; 
} 

इस उलटा नक्शा गणना के बाद दो को बदलने कार्यों

int direct(int x) { return x==0x2122 ? 0 : (x & 63); } 
int inverse(int x) { return invmap[x]; } 

समारोह direct(x) 0 और 63 के बीच की संख्या वापस आ जाएगी, और समारोह inverse(x) 0 और 63 के बीच की संख्या को देखते हुए एक पूर्णांक वापस आ जाएगी है। आपकी सूची में सभी 27 मानों के लिए inverse(direct(x)) == x

1

मैं कुछ सरल (और सस्ते) हैश फ़ंक्शन f के लिए जाना चाहूंगा कि आप f0, f1, ... ऐसे परिवारों में से चुनते हैं जो मूल्य 0..255 मानते हैं। यदि आपका हैश फ़ंक्शन यादृच्छिक होगा, तो जन्मदिन के विरोधाभास से आपके पास उन मूल्यों के लिए कुछ टकराव होंगे, जिनमें आप रुचि रखते हैं, लेकिन बहुत से नहीं।

अब एक साधारण पर्ल (जो कुछ भी) स्क्रिप्ट आपको अपने सेट से उचित फ़ंक्शन चुनकर टकराव को कम करने (या यहां तक ​​कि समाप्त करने) को कम करने के लिए आपके निश्चित मूल्यवान डेटा को प्रीप्रोसेस करने की अनुमति देगा।

इस दृष्टिकोण का लाभ यह है कि आप प्रीप्रोसेसिंग रन को नवीनीकृत कर सकते हैं यदि आप पाते हैं कि आप एक मान भूल गए हैं (जैसा कि आपने पहले ही किया है) या कुछ अजीब देश विचित्र यूनिकोड वर्णों को € 8bit वर्ण सेट में मैप करने का निर्णय लेता है।

और, बीटीडब्ल्यू, मुझे लगता है कि कुछ आईएसओ -885 9- में विशेष वर्णों की मात्रा है? आपके पास जो कुछ है, उससे सेट बहुत बड़ा होना चाहिए, नहीं, नहीं? मैं उन्हें सब ले जाऊंगा।

संपादित करें: कुछ प्रयोग करने के बाद एक छोटे से पर्ल स्क्रिप्ट मुझसे कहता है सभी 577 यूनिकोड कोड अंक कि आईएसओ 8859 से किसी एक एन्कोडिंग में दिखाई देते हैं अलग अलग स्थानों के लिए नक्शे है कि जब सापेक्ष 10007 या 10009 कम कर दिया।

संपादित करें: निम्न तालिका करता है चाल, सीमित सेट के लिए:

wchar_t const uniqTable[91] = { 
[0x7] = L'\u2116' /* № */, 
[0xD] = L'\uFFFD' /* � */, 
[0xE] = L'\u200C' /* ‌ */, 
[0xF] = L'\u200D' /* ‍ */, 
[0x10] = L'\u200E' /* ‎ */, 
[0x11] = L'\u200F' /* ‏ */, 
[0x13] = L'\u2122' /* ™ */, 
[0x15] = L'\u2013' /* – */, 
[0x16] = L'\u2014' /* — */, 
[0x17] = L'\u2015' /* ― */, 
[0x19] = L'\u2017' /* ‗ */, 
[0x1A] = L'\u2018' /* ‘ */, 
[0x1B] = L'\u2019' /* ’ */, 
[0x1C] = L'\u201A' /* ‚ */, 
[0x1E] = L'\u201C' /* “ */, 
[0x1F] = L'\u201D' /* ” */, 
[0x20] = L'\u201E' /* „ */, 
[0x22] = L'\u2020' /* † */, 
[0x23] = L'\u2021' /* ‡ */, 
[0x24] = L'\u2022' /* • */, 
[0x28] = L'\u2026' /* … */, 
[0x32] = L'\u2030' /* ‰ */, 
[0x3B] = L'\u2039' /* ‹ */, 
[0x3C] = L'\u203A' /* › */, 
[0x51] = L'\u20AA' /* ₪ */, 
[0x52] = L'\u20AB' /* ₫ */, 
[0x53] = L'\u20AC' /* € */, 
[0x56] = L'\u20AF' /* ₯ */, 
}; 
+0

अधिकांश पात्रों * और खिड़कियों codepages में हैं उनके संबंधित अक्षरों (सिरिलिक, ग्रीक, हिब्रू, विस्तारित लैटिन, ...) के लिए श्रेणियां, लेकिन मैं यहां कुछ और दुर्लभ यू + 2xxx कोड को समायोजित करने के लिए आवश्यक से अधिक बड़ी तालिकाओं का उपयोग कर रहा था (यूरो साइन, ट्रेडमार्क साइन, स्मार्ट उद्धरण, आदि) –

+0

ठीक है, मैं देखता हूं। लेकिन फिर भी, अलग-अलग पात्रों के सेट पर फिर से शुरू करने की बजाय, मैंने उन सभी को पकड़ने के लिए एक सामान्य समाधान चुना होगा। यदि आप https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859 में तालिका देखते हैं, तो बहुत अधिक नहीं हैं। लेकिन शायद आपको सोचा था कि उन्हें कुछ बड़ा लगता है, 10 बिट थोड़ा अच्छा करना चाहिए। –

+0

वास्तव में बदसूरत यू + 2xxx मामलों को छोड़कर, प्रत्येक प्रविष्टि के 10 बिट्स विरासत चरित्र सेट के लिए पर्याप्त है। मेरे प्रश्न में 0-127 इस तथ्य से आया कि कोई भी उच्च बाइट एएससीआईआईआई पर नक्शा नहीं लगा सकता है, इसलिए मैं इस श्रेणी में संख्याओं को यू + 2xxx वर्णों के लिए पुनर्निर्देशन के रूप में पुन: उपयोग कर सकता हूं। –

0

परीक्षण & त्रुटि, मैं निम्नलिखित कलन विधि पर पहुंचे द्वारा:

#include <assert.h> 
#include <stdio.h> 

static const unsigned CODES[] = { 
    0x200C, 0x200D, 0x200E, 0x200F, 
    0x2013, 0x2014, 0x2015, 0x2017, 
    0x2018, 0x2019, 0x201A, 0x201C, 
    0x201D, 0x201E, 0x2020, 0x2021, 
    0x2022, 0x2026, 0x2030, 0x2039, 
    0x203A, 0x20AA, 0x20AB, 0x20AC, 
    0x20AF, 0x2116, 0x2122 
}; 

static unsigned enc(unsigned value) 
{ 
    return (value & 0x3F) + (value & 0x180)/4; 
} 

static unsigned dec(unsigned value) 
{ 
    return 0x2000 + value + ((value & 0x40) >> 6) * 3 * 
     (0x20 + (value & 0x10) * 2 + (value & 0x20)); 
} 

int main(void) 
{ 
    const unsigned *const END = CODES + sizeof CODES/sizeof *CODES; 
    const unsigned *current = CODES; 
    for(; current < END; ++current) 
    { 
     printf("%04x -> %02x -> %04x\n", 
      *current, enc(*current), dec(enc(*current))); 

     assert(enc(*current) < 0x80); 
     assert(dec(enc(*current)) == *current); 
    } 

    return 0; 
} 

कभी कभी, विकास की धड़कन कोड लिखते समय भी बुद्धिमान डिज़ाइन;)

+0

'enc' का आउटपुट 127 से बहुत बड़ा है। –

+0

@R ..: एल्गोरिदम को प्रतिस्थापित किया गया ... – Christoph

3

यह विधि एक सीमित फाई में गुणा का उपयोग करती है ld:

#define PRIME 0x119 
#define OFFSET1 0x00f 
#define OFFSET2 0x200c 
#define OFFSET3 (OFFSET2 - OFFSET1) 
#define MULTIPLIER 2 
#define INVERSE 0x8d 

unsigned map(unsigned n) 
{ 
    return ((n - OFFSET3) * MULTIPLIER) % PRIME; 
} 

unsigned unmap(unsigned m) 
{ 
    return ((m * INVERSE) + PRIME - OFFSET1) % PRIME + OFFSET2; 
} 

map() अद्वितीय 7 बिट नंबर करने के लिए यूनिकोड अंक बदल देता है, और unmap() रिवर्स करता है। ध्यान दें कि gcc कम से कम x86 कोड को संकलित करने में सक्षम है जो किसी भी विभाजन संचालन का उपयोग नहीं करता है, क्योंकि मॉड्यूलस स्थिर है।

+0

क्या आपने इसे हाथ से बाहर किया या क्या आपके पास ऐसा करने का कोई टूल है? यह निश्चित रूप से मेरे प्रश्न के बारे में सबसे खूबसूरत उत्तर है, हालांकि मैं कुछ ऐसा कर सकता हूं जैसे जेन्स दो सेट के मानचित्र के साथ इन सेटों में * सभी * पात्रों के बारे में बात कर रहा था। –

+0

@ आर .: मैंने '0x119' को' 0x2122 - 0x200c' से पहले के पहले प्राइम के रूप में चुना है, फिर 'ऑफसेट 1' और 'मल्टीप्लीयर' मानों को ब्रूटफोर्स करने के लिए एक संक्षिप्त सी प्रोग्राम लिखा है जो सबसे सीमित सीमा प्रदान करता है। चूंकि वह सीमा '0x7f' से कम थी, इसलिए मैंने वहां रुक दिया और' 2' mod '0x119' के गुणात्मक उलटा गणना की। यदि '0x119' काम नहीं किया था, तो मैं अगले उच्च प्रधान में गया होता। – caf

+0

समस्या के लिए एक अच्छा, साफ दृष्टिकोण; आश्चर्यजनक रूप से पर्याप्त है, हालांकि, मेरा विज्ञापन-प्रसार एल्गोरिदम आपके प्रदर्शन को बेहतर प्रदर्शन करता है, भले ही मेरा डिकोडिंग फ़ंक्शन वास्तव में बदसूरत दिखता है ... – Christoph

संबंधित मुद्दे