ASCII भूलभुलैया संपीड़न


9

चुनौती

ASCII mazes को संपीड़ित करने के लिए विशेष संपीड़न एल्गोरिदम डिज़ाइन करें। आपको एक संपीड़न एल्गोरिथ्म और एक विघटन एल्गोरिथ्म दोनों बनाने की आवश्यकता होगी। आपका स्कोर आपके संकुचित mazes के आकार पर आधारित होगा।

mazes

इन mazes के मुख्य रूप से पात्रों के बने होते हैं (फर्श), +, -, |, और #(दीवारों), और ठीक एक से प्रत्येक ^(शुरू) और $(अंत)। उनमें ASCII अक्षर भी हो सकते हैं, जो फर्श टाइल्स के रूप में गिने जाते हैं। इस चुनौती के प्रयोजनों के लिए, mazes को हल करने की आवश्यकता नहीं है और भूलभुलैया की सामग्री का वास्तविक अर्थ अप्रासंगिक है।

  • + दीवार की कोशिकाओं के लिए उपयोग किया जाएगा जहां कम से कम एक क्षैतिज रूप से आसन्न दीवार सेल है और कम से कम एक लंबवत आसन्न दीवार सेल है।
  • | दीवार की कोशिकाओं के लिए उपयोग किया जाएगा जहां कम से कम एक लंबवत आसन्न दीवार सेल है, लेकिन क्षैतिज रूप से आसन्न दीवार कोशिकाएं नहीं हैं।
  • - दीवार कोशिकाओं के लिए उपयोग किया जाएगा जहां कम से कम एक क्षैतिज रूप से आसन्न दीवार सेल है, लेकिन लंबवत रूप से आसन्न दीवार सेल नहीं है
  • # का उपयोग केवल उन दीवार कोशिकाओं के लिए किया जाएगा जो अन्य दीवार कोशिकाओं के निकट orthogonally नहीं हैं।

सभी mazes आयताकार हैं, लेकिन जरूरी नहीं कि एक नियमित ग्रिड / दीवार संरेखण हो।

को कम करने के लिए Mazes

भूलभुलैया 1

+----+----
|  o |    |
| -- | o--+
|    | |  $
 --^-+-+---

भूलभुलैया 2

+-----+---+
|  a  |   |
^ +-+-+ # |
| | |  B  |
| | | --+ |
|   c   | $
+-------+--

भूलभुलैया 3

----------+-+-+-----+-+
^         | | |     | |
+-- --+R #  | |p| | | |
|     | |       | |   |
+---+ +-+-+-- +-+ | | |
|  m| | | |   |   | | |
| +-+ | | | | | --+ | |
| | |    h  | |   | | |
| | | | | |  #  --+-+ |
|     | | | | |  S|   $
+-----+-+-+-+-+---+----

भूलभुलैया ४

+-----+---+-+---+-------^-----+
|     |x  | |   |     tsrq    |
+-+-- +-- | +--  #  --+---- --+
| |   |           |   |       |
| | | | | +-+-+---+ | +-- | +-+
| | | u | | | |     | |   | | |
| +-+ | | | | +---- +-+---+ | |
| |   | |   |    y  |       w |
| | --+ | --+ +-- | +---- | | |
|     | |   | |   | |     | | |
+-- --+ +-+ | | | | +-- | +-+-+
|     | | |   | | | |   |     |
$ | --+-+ | --+-+ | +-+-+-- --+
| |   |      z|   |   |    v  |
+-+---+-------+---+---+-------+

भूलभुलैया ५

++ -----------+
++-       Beep|
$  ----+---+--+
+-+boop|   |  |
| +--- | | | ++
|      | |  +++
+------+-+--+ ^

भूलभुलैया ६

+-$---------------+-+--
|                 | |j 
| |l ---- # ---+ |  |  
| | |       m  | +--+ |
| | | +-+---- #       |
| | | | |      +----+ |
|o| | | | +----+    | |
|       | |    | -- | |
| | | | | | -+ |    | |
| | | | |  | | +--- | |
| | | | +- | | |   | ++
+-+ |n| |  | ++ +--+ | 
    | |   -+- | |  | +-
+---+ +---    |  | |  ^
|    |     --+ --+ | | 
| -- | |  k  |     | ++
|    | |      +--- | ++
|    |      | |    |  |
+-- -+----  | +----+--+

भूलभुलैया 7

+---+-+-------------+-+^+-----+-------+---+-+---+-+---+-+---+
|   |c|             | | |  c  |       |   | |   | |   |c|   |
+-- | | +-- +-- # | | | +-- --+ +---- +-- | +-+ | | +-+ | --+
|       |   |     | |           |         |   | |c| |       |
| | +-- | +-+-- +-+ +-- # +- # -+-- +-- | | --+ | | | | --+C|
|c| |   | | c   |         |         |c  |             |   | |
+-+-+---+-+-----+---------+---------+---+-------------+---+$|

भूलभुलैया 8

------+-+-+---+-+---+-----------+---+-----+---------------+-+
^     | | |   | |   |           |   |     |      r        | |
+-- | | | t | | +-- +----- # ---+-- +-- --+-- ----+-+ --+ | |
|   |   | | |   |   |         r |   |             | |   |   |
| | | | | +-+ --+ --+-- --------+-- | ----+ --+ | | | --+ | |
| |r| |            rotation               |   | |   |   | | $
+-+-+-+-----------------------------------+---+-+---+---+-+--

भूलभुलैया 9

|$|^--+-+---+-----+-+---+-+-+---+---+-+---+-----+
| |   | |   |     | |   | | | f |   | |   |     |
| +-+ | | # +-+ --+ +-+ | | | # | +-+ +-- | ----+
|   |       | |    f| |           | | |   |   f |
| |F+-+ | | | | +---+ | | | ----+-+ | | --+ --+-+
| |   | | |     |     | | |   f |   |         | |
| | | | +-+-+---+-- | | | +-+-+-+ +-+ +--- # -+ |
| | | |     |   |   |   | | | |   | | |         |
+-+-+ | +---+ --+ | +---+-+ | | --+ f | | | | --+
|     | |         |                 | | | | |   |
| --+f| | | +-- --+--f--+ --+ | ----+ | +-+ +---+
|   |     | |     |     |   | |           |     |
+---+-----+-+-----+-----+---+-+-----------+-----+

भूलभुलैया १०

+-----+-+-----------+
|  q  | |         q |
|Q+-+ | +-+-+-+---- |
$ | |     | | |  q  |
+-+ | | | | | +-- +-+
| |   | |     |   | |
| +-- +-+ |q| +-+ | |
|    q|   | |   |   |
| | | +-- | +-+ | --+
| | | |   | | |     |
+-+-+-+ +-+-+ +-- | |
|       |         | |
+--- # -+ | | +-- | |
|  q      | | |   | ^
+-+ +-- | | +-+ | +-+
| | |   | |q|   |   |
| +-+-+ | +-+-- | | |
|     | | |     | | |
| | | +-+-+-- +-+ +-+
| | |         | q   |
+-+-+---------+-----+

नियम, मान लेना, स्कोर करना

  • मानक खामियों पर रोक लगाई जाती है
    • एक सामान्य कार्यक्रम लिखें, एक नहीं जो केवल दस परीक्षण मामलों के लिए काम करता है। यह किसी भी मनमाने चक्रव्यूह को संभालने में सक्षम होना चाहिए।
  • आप मान सकते हैं कि वास्तव में एक प्रवेश द्वार और एक निकास होगा। प्रवेश और निकास हमेशा भूलभुलैया की सीमा पर होंगे।
  • आप मान सकते हैं कि सभी इनपुट दीवारों का उपयोग करते हैं जो ऊपर उल्लिखित नियमों का पालन करते हैं। आपकी कम्प्रेशन एल्गोरिथ्म में उन नियमों का उल्लंघन करने वाली दीवारों वाले मज़ारों के लिए काम नहीं करना पड़ता है।
  • इनपुट माज़े सॉल्व हो सकते हैं या नहीं भी।
  • आप मान सकते हैं कि भूलभुलैया किसी भी दिशा में 100 वर्णों से बड़ी नहीं होगी।
  • आप मान सकते हैं कि पत्र भूलभुलैया के किनारे पर दिखाई नहीं देंगे। (चूंकि यह उदाहरण दिए गए उदाहरणों के लिए मामला है)
  • आपका स्कोर कुल आकार का है, बाइट्स (ओकटेट्स) में, सभी संपीड़ित माज़ों का।
    • यदि आप अधिक सुविधाजनक पाते हैं तो आप अपने संकुचित भूलभुलैया के प्रतिनिधित्व के रूप में हेक्स, बेस 64, बाइनरी स्ट्रिंग्स या किसी भी समान प्रारूप का उपयोग कर सकते हैं। आपको अभी भी पूरे ऑक्टेट में परिणाम की गणना करनी चाहिए, प्रत्येक भूलभुलैया के लिए गोल किया जाना चाहिए (जैसे 4 बेस 64 अंक 3 बाइट्स हैं, 2 हेक्स अंक 1 बाइट है, 8 बाइनरी अंक 1 बाइट है, आदि ...)
    • सबसे कम स्कोर जीत!

वहाँ एक भूलभुलैया के लिए एक आकार सीमा है?
अज्ञान

@EmbodimentofIgnorance 100x100
बीफस्टर

@Arnauld वास्तव में एक कॉपी-पेस्टिंग मुद्दा था, लेकिन मुझे लगता है कि एसई लाइन के अंत में स्ट्रिप्स रिक्त स्थान को वैसे भी प्रारूपित करता है। हाँ, यह अंतरिक्ष-गद्देदार माना जाता है।
बीफस्टर

@ChasBrown, जो एक मानक खामियों के रूप में गिना जाता है, जिसका अर्थ है कि यह डिफ़ॉल्ट रूप से प्रतिबंधित है।
बीफस्टर

1
@schnaader, जो उचित लगता है उदाहरण के मामलों को देखते हुए।
बीफस्टर

जवाबों:


5

जावास्क्रिप्ट (Node.js) , स्कोर =  586 541 503 492  479 बाइट्स

दीवारों को हफमैन-एन्कोडेड स्ट्रीम बिट्स के रूप में संग्रहीत किया जाता है, जिसमें यह वर्णन किया जाता है कि क्या कोई भविष्यवाणी फ़ंक्शन सही अनुमान दे रहा है या नहीं।

विशेष वर्ण के रूप में संग्रहीत हैं (,सी), कहाँ पे पिछले विशेष चरित्र से दूरी है और सी ASCII कोड है।

इसे ऑनलाइन आज़माएं!

सामान्य

const HUFFMAN = [
  '00',       // 0000
  '010',      // 0001
  '1001',     // 0010
  '11100',    // 0011
  '011',      // 0100
  '101',      // 0101
  '11110',    // 0110
  '100010',   // 0111
  '110',      // 1000
  '11101',    // 1001
  '1111100',  // 1010
  '1111101',  // 1011
  '10000',    // 1100
  '1111110',  // 1101
  '100011',   // 1110
  '1111111'   // 1111
];

let bin = (n, w) => n.toString(2).padStart(w, '0');

let wallShape = (row, x, y) => {
  let vWall = (row[y - 1] || [])[x] | (row[y + 1] || [])[x],
      hWall = row[y][x - 1] | row[y][x + 1];

  return ' -|+'[row[y][x] ? vWall * 2 | hWall : 0];
}

let predictWall = (row, x, y, w, h) => {
  let prvRow = row[y - 1] || [];
  return !x | !y | x == w - 1 | y == h - 1 | (prvRow[x] | row[y][x - 1]) & !prvRow[x - 1];
}

दबाव

let pack = str => {
  let row = str.split('\n').map(r => [...r]),
      w = row[0].length,
      h = row.length;

  let wall = row.map((r, y) => r.map((c, x) => +/[-+|]/.test(c)));

  if(row.some((r, y) => r.some((c, x) => wall[y][x] && wallShape(wall, x, y) != c))) {
    throw "invalid maze";
  }

  row = wall.map((r, y) => r.map((v, x) => predictWall(wall, x, y, w, h) ^ v));
  row = row.map(r => r.join('')).join('');
  row = row.replace(/.{1,4}/g, s => HUFFMAN[parseInt(s.padEnd(4, '0'), 2)]);

  str =
    str.replace(/[\n|+-]/g, '').replace(/ *(\S)/g, (s, c) => {
      let n = c.charCodeAt(),
          i = '^$#'.indexOf(c);

      return (
        bin(s.length > 63 ? 0xFC000 | s.length - 1 : s.length - 1, 6) +
        bin(~i ? i : n < 91 ? (n > 80 ? 0x1F0 : 0x1E0) | ~-n & 15 : n - 94, 5)
      );
    }).trim();

  return (
    Buffer.from(
      (bin(w, 7) + bin(h, 7) + row + str)
      .match(/.{1,8}/g).map(s => parseInt(s.padEnd(8, '0'), 2))
    ).toString('binary')
  );
}

विसंपीड़न

let unpack = str => {
  str = [...str].map(c => bin(c.charCodeAt(), 8)).join('');

  let x, y, n, i, s,
      ptr = 0,
      read = n => parseInt(str.slice(ptr, ptr += n), 2),
      w = read(7),
      h = read(7),
      row = [];

  for(x = s = ''; s.length < w * h;) {
    ~(i = HUFFMAN.indexOf(x += read(1))) && (s += bin(i, 4), x = '');
  }
  for(i = y = 0; y < h; y++) {
    for(row[y] = [], x = 0; x < w; x++) {
      row[y][x] = predictWall(row, x, y, w, h) ^ s[i++];
    }
  }

  row = row.map((r, y) => r.map((c, x) => wallShape(row, x, y)));

  for(i = 0; str[ptr + 10];) {
    for(
      n = (n = read(6)) == 0x3F ? read(14) + 1 : n + 1;
      n -= row[i / w | 0][i % w] == ' ';
      i++
    ) {}

    row[i / w | 0][i % w] = String.fromCharCode(
      (n = read(5)) >= 0x1E ? read(4) + (n == 0x1F ? 81 : 65) : [94, 36, 35][n] || n + 94
    );
  }
  return row.map(r => r.join('')).join('\n');
}

कैसे?

एक भूलभुलैया एक बिट स्ट्रीम के रूप में एन्कोड किया गया है जो अंततः एक स्ट्रिंग में परिवर्तित हो जाता है।

हैडर

शीर्ष लेख में निम्न शामिल हैं:

  • चौड़ाई w 7 बिट्स पर
  • ऊँचाईं 7 बिट्स पर

दीवार डेटा

हम पूरे चक्रव्यूह के माध्यम से चलते हैं और यह अनुमान लगाने का प्रयास करते हैं कि क्या अगली सेल पहले की गई कोशिकाओं के आधार पर दीवार है या नहीं। हम उत्सर्जन करते हैं0 अगर हम सही हैं, या ए 1 अगर हम गलत हैं।

यह (उम्मीद) काफी अधिक के साथ सुधार बिट्स के एक अनुक्रम में परिणाम है 0से है 1'है। यह अनुक्रम nibbles में विभाजित है और हार्ड-कोडित हफ़मैन कोड का उपयोग करके संग्रहीत किया गया है:

  • 000000
  • 0100001
  • 10010010
  • 111000011
  • 0110100
  • आदि।

दीवार को डीकोड करने के लिए डब्ल्यूnसड़न रोकनेवाला दिनचर्या समान भविष्यवाणी की गणना करता है पीn और यदि आवश्यक हो तो सुधार बिट का उपयोग करके परिणाम को टॉगल करता है सीn:

डब्ल्यूn=पीnसीn

अंतिम दीवार की आकृतियाँ एक तरह से निक की जाती हैं जो निक केनेडी के उत्तर के समान है ।

विशेष वर्ण

प्रत्येक विशेष वर्ण इनकोडिंग है:

  • दूरी माइनस 1 पिछले विशेष चरित्र से (दीवारों की अनदेखी):

    • 6 बिट्स पर अगर यह इससे कम है 63
    • या के रूप में 111111 + 14 बिट अन्यथा (परीक्षण मामलों में उपयोग नहीं किया जाता है, लेकिन सिद्धांत में आवश्यक है)
  • चरित्र का कोड:

    • 5 बिट्स पर यह है कि अगर ^, $, #या[a-z]
    • या 11110 + 4 बिट्स के लिए [A-O]
    • या 11111 + 4 बिट्स के लिए [P-Z]

क्या आपने संपीड़न एल्गोरिदम के अलावा अन्य की कोशिश की है deflate? शेल्फ पर एक बहुत कुछ कर रहे हैं!
२१

कोई नियम नहीं है जो कहता है कि उसे TIO में काम करना है!
११:

O_o अच्छा, आश्चर्य है कि अगर दशमलव संपीड़न सभी में मदद करेगा (मूल रूप से हफ़मैन के विपरीत, अंतरिक्ष 0 से 1 है, तो मनमाने आकार के साथ वर्गों में विभाजित किया गया है (<1 पाठ्यक्रम के), और एन्कोडिंग सबसे छोटा बाइनरी नंबर है जो भीतर गिरता है अंतरिक्ष का सही टुकड़ा
केवल

@ ASCII- केवल दशमलव कोडिंग (उर्फ अंकगणित कोडिंग) निश्चित रूप से संपीड़न अनुपात में सुधार करना चाहिए, लेकिन शायद इस तरह के एक छोटे डेटा स्ट्रीम पर एक छोटे से मार्जिन द्वारा। मुझे यकीन है कि अंकगणित कोडिंग पर स्विच करने से पहले हफ़मैन कोडिंग और / या भविष्यवाणी समारोह में सुधार करना संभव है, हालांकि (दोनों वास्तव में अभी मूल हो रहे हैं)।
अरनौलद

@ ASCII- केवल उदाहरण के लिए, मुझे शायद लंबे समय तक कोड (नीबल्स का उपयोग करना मनमाना है) का प्रयास करना चाहिए। मैं हेडर में 1-बिट फ़्लैग जोड़कर बता सकता हूं कि क्या डेटा को डिफ़ॉल्ट स्थिर हफ़मैन कोड के साथ या डायनेमिक कोड के साथ अनपैक किया जाना चाहिए (यदि यह कुछ mazes के संपीड़न को बेहतर बनाने के लिए निकला है)। एक चीज जो मैंने कोशिश की थी वह भूलभुलैया को ९ ० ° तक घुमाना और यह देखना था कि क्या बेहतर कंप्रेस कर रहा है। लेकिन वह कुल मिलाकर 1 बाइट बचा रहा था।
अरनौलद

4

आर, स्कोर 668 बाइट्स

यह इस तथ्य का लाभ उठाता है कि दीवार का चरित्र उसके परिवेश से निर्धारित होता है। जैसे, दीवार के पात्रों को बिट्स के रूप में एन्कोड किया जा सकता है। शेष जानकारी जिसे संग्रहीत करने की आवश्यकता है, वह भूलभुलैया के आयाम, प्रारंभ और समाप्ति की स्थिति और किसी भी अन्य गैर-दीवार पात्रों की स्थिति है। चूंकि गैर-दीवार वर्ण ASCII हैं, इसलिए मैंने प्रत्येक बाइट के सबसे महत्वपूर्ण बिट का उपयोग यह दर्शाने के लिए किया है कि क्या कोई अन्य वर्ण है जो इस प्रकार है ताकि mazes में कुछ शब्दों के लिए प्रत्येक वर्ण का स्थान संग्रहीत न हो अलग से। यह भी ध्यान दें कि 256 वर्णों से कम या उसके बराबर वाले माज़ों के लिए (जैसे 16x16 या समतुल्य आयताकार मेज़ों के लिए), पदों को एक बाइट में संग्रहीत किया जा सकता है, जबकि बड़े मज़ारों के लिए पोज़िशन को दो बाइट्स की आवश्यकता होती है।

उपयोगिता कार्य

r <- as.raw

int_as_raw <- function(int, bytes = 2) {
  if (bytes == 1) {
    r(int)
  } else {
    do.call(c, lapply(int, function(.x) r(c(.x %/% 256, .x %% 256))))
  }
}

raw_as_int <- function(raw, bytes = 2) {
  if (bytes == 1) {
    as.integer(raw)
  } else {
    sapply(
      seq(1, length(raw) - 1, 2),
      function(.x) as.integer(as.integer(raw[.x + 0:1]) %*% c(256, 1))
    )
  }
}

संपीड़न एल्गोरिदम

compress_maze <- function(maze) {
  maze_array <- do.call(rbind, strsplit(maze, ""))
  simple_maze <- r(maze_array %in% c("+", "#", "-", "|"))
  simple_maze <- packBits(c(simple_maze, rep(r(0), (8 - length(simple_maze)) %% 8)))
  maze_dim <- int_as_raw(dim(maze_array), 1)
  bytes_needed <- 1 + (length(maze_array) > 256)
  start_finish <- int_as_raw(sapply(c("^", "$"), function(.x) which(maze_array == .x)) - 1, bytes = bytes_needed)
  other_ascii_locs_rle <- rle(!(maze_array %in% c(" ", "+", "#", "-", "|", "$", "^")))
  other_ascii_locs <- cumsum(
    c(1, other_ascii_locs_rle$lengths[-length(other_ascii_locs_rle$lengths)])
  )[other_ascii_locs_rle$values]
  other_ascii_locs_length <- other_ascii_locs_rle$lengths[other_ascii_locs_rle$values]

  encode_ascii <- function(loc, len) {
    text <- charToRaw(paste(maze_array[loc:(loc + len - 1)], collapse = ""))
    if (len > 1) {
      text[1:(len - 1)] <- text[1:(len - 1)] | r(128)
    }
    c(int_as_raw(loc - 1, bytes = bytes_needed), text)
  }

  other_ascii_encoded <- Map(encode_ascii,
    other_ascii_locs,
    other_ascii_locs_length
    )
  other_ascii_encoded <- do.call(c, other_ascii_encoded)
  c(maze_dim, simple_maze, start_finish, other_ascii_encoded)
}

विघटन एल्गोरिथ्म

decompress_maze <- function(c_maze) {
  dim_maze <- as.integer(c_maze[1:2])
  len_maze <- prod(dim_maze)
  len_maze_b <- ceiling(len_maze / 8)
  bit_maze <- rawToBits(c_maze[-(1:2)])[1:len_maze]
  dim(bit_maze) <- dim_maze
  bit_maze[-1, ] <- bit_maze[-1, ] | rawShift(bit_maze[-nrow(bit_maze), ] & r(1), 1)
  bit_maze[-nrow(bit_maze), ] <- bit_maze[-nrow(bit_maze), ] | rawShift(bit_maze[-1, ] & r(1), 1)
  bit_maze[, -1] <- bit_maze[, -1] | rawShift(bit_maze[, -ncol(bit_maze)] & r(1), 2)
  bit_maze[, -ncol(bit_maze)] <- bit_maze[, -ncol(bit_maze)] | rawShift(bit_maze[, -1] & r(1), 2)
  bit_maze[(bit_maze & r(1)) == r(0)] <- r(0)
  array_maze <- c(" ", "#", "|", "-", "+")[(as.integer(bit_maze) + 1) %/% 2 + 1]
  dim(array_maze) <- dim_maze
  bytes_needed <- 1 + (len_maze > 256)
  start_finish <- raw_as_int(c_maze[2 + len_maze_b + 1:(bytes_needed * 2)], bytes_needed) + 1
  array_maze[start_finish] <- c("^", "$")
  i <- 3 + len_maze_b + 2 * bytes_needed
  while (i < length(c_maze)) {
    loc <- raw_as_int(c_maze[i + 1:bytes_needed - 1], bytes_needed) + 1
    i <- i + bytes_needed
    text <- character(0)
    while (c_maze[i] & r(128)) {
      text <- c(text, rawToChar(c_maze[i] & r(127)))
      i <- i + 1
    }
    text <- c(text, rawToChar(c_maze[i]))
    array_maze[loc:(loc + length(text) - 1)] <- text
    i <- i + 1
  }
  apply(array_maze, 1, paste, collapse = "")
}

इसे ऑनलाइन आज़माएं!


मुझे पता था कि आप दीवारों को बिट्स के रूप में स्टोर करने में सक्षम होंगे, लेकिन मुझे गैर-दीवार चरित्र स्थिति डेटा को संपीड़ित करने के लिए आपका दृष्टिकोण पसंद है। +1
नील
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.