লাতিন বর্গাকার সংক্ষেপণ


31

একজন ল্যাটিন বর্গক্ষেত্র একটি বর্গক্ষেত্র কোন পুনরাবৃত্তি করেছে যে সারি বা কলামে প্রতীক হল:

13420
21304
32041
04213
40132

এবং অনেক সুডোকু খেলোয়াড় জানেন যে, বাকি সংখ্যাগুলি কমাতে আপনার সমস্ত সংখ্যার দরকার নেই।

আপনার চ্যালেঞ্জটি হ'ল ল্যাটিন স্কোয়ারকে যথাসম্ভব কয়েকটি বাইটে সংকুচিত করা। আপনার এক বা দুটি প্রোগ্রাম (গুলি) সরবরাহ করতে হবে যা সংকোচিত / ডিকম্প্রেস করে।

বিভিন্ন তথ্য:

  • ব্যবহৃত নম্বরগুলি সর্বদা থাকবে 0..N-1, যেখানে Nবর্গাকার প্রান্তের দৈর্ঘ্য এবংN<=25
  • ডিকম্প্রেশনে, লাতিন বর্গটি অবশ্যই ইনপুটটির মতো হবে।
  • আপনার প্রোগ্রাম (গুলি) কেবলমাত্র আমি সরবরাহ করেছি তা নয়, কোনও লাতিন বর্গকে (সর্বাধিক বর্গ আকারের মধ্যে ) সংকুচিত করতে সক্ষম হওয়া উচিত । সংক্ষেপণের অনুপাতও একই রকম হওয়া উচিত।
  • আপনার স্কোরটি পাওয়ার জন্য আপনাকে অবশ্যই সংক্ষেপণ এবং ডিকম্প্রেসার চালাতে হবে (মহাবিশ্বের কোনও রান-টাইম নেই)

পরীক্ষাগুলি পাওয়া যাবে গিথুবেআপনার স্কোর সংকুচিত পরীক্ষার কেসগুলির মোট আকার।

সম্পাদনা: July ই জুলাই ২০:০ As তারিখে, আমি পরীক্ষার কেসগুলি আপডেট করেছি (একটি প্রজন্মের সমস্যা সমাধানের জন্য)। নতুন পরীক্ষার ক্ষেত্রে আপনার প্রোগ্রামটি পুনরায় চালু করুন। ধন্যবাদ আন্ডারস ক্যাসরগ


1
ঠিক আছে, সংজ্ঞা অনুসারে, কোনও চিহ্ন ব্যবহার করা যেতে পারে, তবে আমার পরীক্ষার কেসগুলি যদিও ব্যবহার করতেই ঘটে :)0n-1
নাথান মেরিল


3
@ নাথানমারিল ভাল, পয়েন্টটি কেবলমাত্র nবিভিন্ন চিহ্ন ব্যবহার করার অনুমতি পেয়েছিল । : পি
মার্টিন এন্ডার

1
@ ডেভিডিসি এটির কোনও ব্যাপার নয় কারণ আকারটি বাইটে পরিমাপ করা হয় ।
flawr

2
আপনার 25 পরীক্ষার বিষয় 19 সারি এবং তুচ্ছ ল্যাটিন বর্গক্ষেত্র যার কলাম permuting দ্বারা উত্পন্ন হয় (ব্যতীত 4, 6, 8, 10, 12, 14 সমস্ত) ( আমি , ) এন্ট্রি আমি + + গেলিক ভাষার এন । এটি এলোমেলো ল্যাটিন স্কোয়ারের চেয়ে অনেক বেশি সংকোচনে তাদেরকে সহজ করে তোলে। যদিও আপনার বিধিগুলি বলছে যে সমস্ত লাতিন স্কোয়ারের জন্য আমাদের একই সংকোচন অনুপাত থাকা উচিত, দুর্ঘটনাক্রমে এটি সহজেই ভাঙ্গা সহজ। পরীক্ষার কেসগুলি আরও প্রতিনিধি হওয়া উচিত।
অ্যান্ডারস কাসের্গ

উত্তর:


10

পাইথন, 1281.375 1268.625 বাইট

আমরা ল্যাটিন স্কোয়ারকে একটি সময়ে "সিদ্ধান্ত" এনকোড করি, যেখানে প্রতিটি সিদ্ধান্ত এই তিনটি ফর্মের মধ্যে একটির হয়:

  • কোন সংখ্যাটি সারিতে চলে যায় আমি , কলাম জে ;
  • সারিতে আমি , কোন কলামে সংখ্যাটি কে যাবে ;
  • কলামে জে , কোন সারিটি কে যাবে

প্রতিটি পদক্ষেপে, আমরা পূর্ববর্তী সিদ্ধান্তের উপর ভিত্তি করে সমস্ত যৌক্তিক সূচনাগুলি তৈরি করি, তারপরে সম্ভাব্য পছন্দগুলির সংক্ষিপ্ত সংখ্যার সাথে সিদ্ধান্তটি বেছে নেই, যার ফলে প্রতিনিধিত্ব করার জন্য বিটগুলির ক্ষুদ্রতম সংখ্যার প্রয়োজন।

পছন্দগুলি একটি সাধারণ গাণিতিক ডিকোডার দ্বারা সরবরাহ করা হয় (পছন্দগুলির সংখ্যা অনুসারে ডিভ / মোড)। তবে এটি এনকোডিংয়ে কিছু অপ্রয়োজনীয়তা ছেড়ে দেয়: যদি কে এমন স্কোয়ারে বিভক্ত হয় যেখানে সমস্ত পছন্দের সংখ্যার গুণফল এম , তবে কে + এম , কে + 2⋅ মি , কে + 3⋅ মি ,… একই স্কোয়ারে ডিকোড করুন শেষে কিছু বাকী রাজ্যের সাথে।

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

import numpy as np

class Latin(object):
    def __init__(self, size):
        self.size = size
        self.possible = np.full((size, size, size), True, dtype=bool)
        self.count = np.full((3, size, size), size, dtype=int)
        self.chosen = np.full((3, size, size), -1, dtype=int)

    def decision(self):
        axis, u, v = np.unravel_index(np.where(self.chosen == -1, self.count, self.size).argmin(), self.count.shape)
        if self.chosen[axis, u, v] == -1:
            ws, = np.rollaxis(self.possible, axis)[:, u, v].nonzero()
            return axis, u, v, list(ws)
        else:
            return None, None, None, None

    def choose(self, axis, u, v, w):
        t = [u, v]
        t[axis:axis] = [w]
        i, j, k = t
        assert self.possible[i, j, k]
        assert self.chosen[0, j, k] == self.chosen[1, i, k] == self.chosen[2, i, j] == -1

        self.count[1, :, k] -= self.possible[:, j, k]
        self.count[2, :, j] -= self.possible[:, j, k]
        self.count[0, :, k] -= self.possible[i, :, k]
        self.count[2, i, :] -= self.possible[i, :, k]
        self.count[0, j, :] -= self.possible[i, j, :]
        self.count[1, i, :] -= self.possible[i, j, :]
        self.count[0, j, k] = self.count[1, i, k] = self.count[2, i, j] = 1
        self.possible[i, j, :] = self.possible[i, :, k] = self.possible[:, j, k] = False
        self.possible[i, j, k] = True
        self.chosen[0, j, k] = i
        self.chosen[1, i, k] = j
        self.chosen[2, i, j] = k

def encode_sized(size, square):
    square = np.array(square, dtype=int)
    latin = Latin(size)
    chosen = np.array([np.argmax(square[:, :, np.newaxis] == np.arange(size)[np.newaxis, np.newaxis, :], axis=axis) for axis in range(3)])
    num, denom = 0, 1
    while True:
        axis, u, v, ws = latin.decision()
        if axis is None:
            break
        w = chosen[axis, u, v]
        num += ws.index(w)*denom
        denom *= len(ws)
        latin.choose(axis, u, v, w)
    return num

def decode_sized(size, num):
    latin = Latin(size)
    denom = 1
    while True:
        axis, u, v, ws = latin.decision()
        if axis is None:
            break
        if not ws:
            return None, 0
        latin.choose(axis, u, v, ws[num % len(ws)])
        num //= len(ws)
        denom *= len(ws)
    return latin.chosen[2].tolist(), denom

def compress(square):
    size = len(square)
    assert size > 0
    num = encode_sized(size, square)
    while size > 1:
        size -= 1
        square, denom = decode_sized(size, num)
        num += denom
    return '{:b}'.format(num + 1)[1:]

def decompress(bits):
    num = int('1' + bits, 2) - 1
    size = 1
    while True:
        square, denom = decode_sized(size, num)
        num -= denom
        if num < 0:
            return square
        size += 1

total = 0
with open('latin_squares.txt') as f:
    while True:
        square = [list(map(int, l.split(','))) for l in iter(lambda: next(f), '\n')]
        if not square:
            break

        bits = compress(square)
        assert set(bits) <= {'0', '1'}
        assert square == decompress(bits)
        print('Square {}: {} bits'.format(len(square), len(bits)))
        total += len(bits)

print('Total: {} bits = {} bytes'.format(total, total/8.0))

আউটপুট:

Square 1: 0 bits
Square 2: 1 bits
Square 3: 3 bits
Square 4: 8 bits
Square 5: 12 bits
Square 6: 29 bits
Square 7: 43 bits
Square 8: 66 bits
Square 9: 94 bits
Square 10: 122 bits
Square 11: 153 bits
Square 12: 198 bits
Square 13: 250 bits
Square 14: 305 bits
Square 15: 363 bits
Square 16: 436 bits
Square 17: 506 bits
Square 18: 584 bits
Square 19: 674 bits
Square 20: 763 bits
Square 21: 877 bits
Square 22: 978 bits
Square 23: 1097 bits
Square 24: 1230 bits
Square 25: 1357 bits
Total: 10149 bits = 1268.625 bytes

আমি এই কোডটি আইডিয়োনে চেষ্টা করছি, তবে এটি কেবল রানটাইম ত্রুটি দেয়। আমি এফ ফাইলের পরিবর্তে স্টিডিন ব্যবহার করে এটি পরিবর্তন করেছি। ideone.com/fKGSQd
edc65

@ edc65 এটি কাজ করে না কারণ আইডিয়নের নুমপি পুরানো।
ডেনিস

@ edc65 আইডিয়নের NumPy 1.8.2 রয়েছে যা এর জন্য খুব পুরানো np.stack()np.array([…])এক্ষেত্রে এটি প্রতিস্থাপন করা যেতে পারে এবং আমি বর্তমান সংস্করণে এটি করেছি।
অ্যান্ডারস কাসরগ

Hmmm। সমস্ত স্কোয়ার কি একটি বাইট স্ট্রিমে সঞ্চিত? তাদের আকারের তথ্যগুলি কি সংরক্ষণ করা হয়, বা ডিকোডারটি ধরে নেয় যে সেগুলি আকার 1,2,3,… ইত্যাদি?
সার্জে বোর্স

@ সার্জবর্স্চ প্রতিটি স্কোয়ার একটি পৃথক বিট প্রবাহে সংকুচিত হয়। আমি বর্ণিত অ্যালগরিদমটি ব্যবহার করে ডিকম্প্রেসার বিট স্ট্রিম থেকে বর্গাকার আকারটি সুস্পষ্টভাবে পুনরুদ্ধার করে। কোন অনুমান ব্যবহৃত হয় না।
অ্যান্ডারস কাসের্গ

7

ম্যাটল্যাব, 3'062.5 2'888.125 বাইট

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

সমস্ত পরীক্ষার ক্ষেত্রে যোগফল 23'105 বিট বা 2'888.125 বাইট। (তবুও আপডেট হওয়া পরীক্ষার কেসগুলি ধরে রাখে, কারণ আমার আউটপুটগুলির আকার কেবল ইনপুট আকারের উপর নির্ভর করে))

function bin=compress(a)
%get rid of last row and column:
s=a(1:end-1,1:end-1);
s = s(:)';
bin = [];
%choose bit depth:
bitDepth = ceil(log2(numel(a(:,1))));
for x=s;
    bin = [bin, dec2bin(x,bitDepth)];
end
end

function a=decompress(bin)
%determine bit depth
N=0;
f=@(n)ceil(log2(n)).*(n-1).^2;
while f(N)~= numel(bin)
    N=N+1; 
end
bitDepth = ceil(log2(N));
%binary to decimal:
assert(mod(numel(bin),bitDepth)==0,'invalid input length')
a=[];
for k=1:numel(bin)/bitDepth;
    number = bin2dec([bin(bitDepth*(k-1) + (1:bitDepth)),' ']);
    a = [a,number];    
end
n = sqrt(numel(a));
a = reshape(a,n,n);
disp(a)
%reconstruct last row/column:
n=size(a,1)+1;
a(n,n)=0;%resize
%complete rows:
v = 0:n-1;
for k=1:n
    a(k,n) = setdiff(v,a(k,1:n-1));
    a(n,k) = setdiff(v,a(1:n-1,k));
end
end

আপনি একটি ভেরিয়েবল বিটরেট ব্যবহার করে আরও কিছুটা সংক্ষেপ করতে পারেন, যেমন n=9..164 বিটের জন্য যথেষ্ট for
কার্ল ন্যাপফ

@ কার্লনাপফ আপনি তখন বিভিন্ন দৈর্ঘ্যের শব্দগুলিকে কীভাবে বৈষম্য করবেন? আমি যতদূর জানি আপনার তখন অতিরিক্ত উপসর্গ দরকার, তাই না?
flawr

একটি সংকোচনের মধ্যে পরিবর্তনশীল নয়, আরও স্কোয়ারের আকারের উপর নির্ভর করে। যদি এন> 16 থাকে তবে 5 টি বিট স্থির করে ব্যবহার করুন, যদি 8 <n <= 16 4 বিট স্থির করে ব্যবহার করেন।
কার্ল নেপফ

ওহ ঠিক এই অর্থ তোলে, আপনাকে ধন্যবাদ!
flawr

3
একই কারণে আপনি এটি অন্য উপায়ে করছেন, এটি সম্ভবত আপনি যেভাবে অভ্যস্ত ছিলেন। =)
flawr

7

পাইথন 3, 10772 বিট (1346.5 বাইট)

def compress(rows):
    columns = list(zip(*rows))
    size = len(rows)
    symbols = range(size)
    output = size - 1
    weight = 25
    for i in symbols:
        for j in symbols:
            choices = set(rows[i][j:]) & set(columns[j][i:])
            output += weight * sorted(choices).index(rows[i][j])
            weight *= len(choices)
    return bin(output + 1)[3:]

def decompress(bitstring):
    number = int('1' + bitstring, 2) - 1
    number, size = divmod(number, 25)
    size += 1
    symbols = range(size)
    rows = [[None] * size for _ in symbols]
    columns = [list(column) for column in zip(*rows)]
    for i in symbols:
        for j in symbols:
            choices = set(symbols) - set(rows[i]) - set(columns[j])
            number, index = divmod(number, len(choices))
            rows[i][j] = columns[j][i] = sorted(choices)[index]
    return rows

সম্মিলিত পরীক্ষার কেসগুলি সংকোচনের জন্য এবং সংক্ষেপিত করতে 0.1 সেকেন্ড সময় নেয়।

আইডিয়নে স্কোর যাচাই করুন ।


ওহ, বোঝাতে যত্ন?
নাথান মেরিল

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

আমি আপনার কোডটি কী করছে তা সম্পূর্ণরূপে নিশ্চিত নই, তবে শেষ পংক্তিটি ফেলে রেখে সংকোচনের সময় সমাধান করা কি সম্ভব নয়?
Yytsi

@TuukkaX যখন শুধুমাত্র একটি সম্ভাব্য প্রতীক আছে len(possible)হয় 1 এবং possible.index(rows[i][j])হয় 0 যাতে প্রতীক কোন খরচ এনকোড করা হয়।
ডেনিস

হ্যাঁ, নতুন পরীক্ষার কেসগুলি 6 টি বিট সংরক্ষণ করেছে। :)
ডেনিস

3

জে , 2444 বাইট

A.পূর্ণসংখ্যার [0, n) এর ক্রমবিন্যাস এবং ক্রমুঠনের সূচকগুলিতে রূপান্তর করতে এবং অন্তর্নির্মিত করতে অন্তর্নিহিতদের উপর নির্ভর করে ।

সংক্ষিপ্ত, 36 বাইট

({:a.)joinstring<@(a.{~255&#.inv)@A.

ইনপুটটি 2d ​​অ্যারে যা লাতিন বর্গকে উপস্থাপন করে। প্রতিটি সারি একটি অনুগমন সূচকে রূপান্তরিত হয়, এবং সেই সূচকটি বেস 255 ডিজিটের তালিকায় রূপান্তরিত হয় এবং একটি ASCII মান দ্বারা প্রতিস্থাপিত হয়। প্রতিটি স্ট্রিং পরে 255 এ ASCII অক্ষর ব্যবহার করে যোগদান করা হয়।

ডিসম্প্রেস, 45 বাইট

[:(A.i.@#)[:(_&,(255&#.&x:);._1~1,255&=)u:inv

প্রতিটি ASCII মান 255 এর ইনপুট স্ট্রিংকে বিভক্ত করে এবং প্রতিটি গ্রুপকে 255 সংখ্যা বেস হিসাবে পার্স করে। তারপরে গোষ্ঠীর সংখ্যা ব্যবহার করে, পূর্ণসংখ্যার একটি তালিকা তৈরি করুন [0, দৈর্ঘ্য) এবং প্রতিটি সূচী অনুসারে এটিকে পরমাণ করুন এবং এটি 2 ডি অ্যারে হিসাবে ফিরিয়ে দিন।


2

পাইথন, 6052 4521 3556 বাইট

compressবর্গক্ষেত্রটিকে বহুমুখী স্ট্রিং হিসাবে গ্রহণ করে, উদাহরণগুলির মতো এবং বাইনারি স্ট্রিং প্রদান করে, যেখানে decompressবিপরীত হয়।

import bz2
import math

def compress(L):
 if L=="0": 
  C = []
 else:
  #split elements
  elems=[l.split(',') for l in L.split('\n')]
  n=len(elems)
  #remove last row and col
  cropd=[e[:-1] for e in elems][:-1]
  C = [int(c) for d in cropd for c in d]

 #turn to string
 B=map(chr,C)
 B=''.join(B)

 #compress if needed
 if len(B) > 36:
  BZ=bz2.BZ2Compressor(9)
  BZ.compress(B)
  B=BZ.flush()

 return B

def decompress(C):

 #decompress if needed
 if len(C) > 40:
  BZ=bz2.BZ2Decompressor()
  C=BZ.decompress(C)

 #return to int and determine length
 C = map(ord,C)
 n = int(math.sqrt(len(C)))
 if n==0: return "0"

 #reshape to list of lists
 elems = [C[i:i+n] for i in xrange(0, len(C), n)]

 #determine target length
 n = len(elems[0])+1
 L = []
 #restore last column
 for i in xrange(n-1):
  S = {j for j in range(n)}
  L.append([])
  for e in elems[i]:
   L[i].append(e)
   S.remove(e)
  L[i].append(S.pop())
 #restore last row
 L.append([])
 for col in xrange(n):
  S = {j for j in range(n)}
  for row in xrange(n-1):
   S.remove(L[row][col])
  L[-1].append(S.pop())
 #merge elements
 orig='\n'.join([','.join([str(e) for e in l]) for l in L])
 return orig

শেষ সারি + কলামটি সরান এবং বাকীটি জিপ করুন।

  • সম্পাদনা 1: ভাল base64প্রয়োজন মনে হয় না
  • সম্পাদনা 2: এখন কাটা টেবিলটিকে বাইনারি স্ট্রিংয়ে রূপান্তর করা হয় এবং প্রয়োজনে কেবল সংক্ষেপণ

2

পাইথন 3, 1955 বাইট

তবুও আরেকটি যা ক্রমান্বয়ে সূচকগুলি ব্যবহার করে ...

from math import factorial

test_data_name = 'latin_squares.txt'

def grid_reader(fname):
    ''' Read CSV number grids; grids are separated by empty lines '''
    grid = []
    with open(fname) as f:
        for line in f:
            line = line.strip()
            if line:
                grid.append([int(u) for u in line.split(',') if u])
            elif grid:
                yield grid
                grid = []
    if grid:
        yield grid

def show(grid):
    a = [','.join([str(u) for u in row]) for row in grid]
    print('\n'.join(a), end='\n\n')

def perm(seq, base, k):
    ''' Build kth ordered permutation of seq '''
    seq = seq[:]
    p = []
    for j in range(len(seq) - 1, 0, -1):
        q, k = divmod(k, base)
        p.append(seq.pop(q))
        base //= j
    p.append(seq[0])
    return p

def index(p):
    ''' Calculate index number of sequence p,
        which is a permutation of range(len(p))
    '''
    #Generate factorial base code
    fcode = [sum(u < v for u in p[i+1:]) for i, v in enumerate(p[:-1])]

    #Convert factorial base code to integer
    k, base = 0, 1
    for j, v in enumerate(reversed(fcode), 2):
        k += v * base
        base *= j
    return k

def encode_latin(grid):
    num = len(grid)
    fbase = factorial(num)

    #Encode grid rows by their permutation index,
    #in reverse order, starting from the 2nd-last row
    codenum = 0
    for row in grid[-2::-1]:
        codenum = codenum * fbase + index(row)
    return codenum

def decode_latin(num, codenum):
    seq = list(range(num))
    sbase = factorial(num - 1)
    fbase = sbase * num

    #Extract rows
    grid = []
    for i in range(num - 1):
        codenum, k = divmod(codenum, fbase)
        grid.append(perm(seq, sbase, k))

    #Build the last row from the missing element of each column
    allnums = set(seq)
    grid.append([allnums.difference(t).pop() for t in zip(*grid)])
    return grid

byteorder = 'little'

def compress(grid):
    num = len(grid)
    codenum = encode_latin(grid)
    length = -(-codenum.bit_length() // 8)
    numbytes = num.to_bytes(1, byteorder)
    codebytes = codenum.to_bytes(length, byteorder)
    return numbytes + codebytes

def decompress(codebytes):
    numbytes, codebytes= codebytes[:1], codebytes[1:]
    num = int.from_bytes(numbytes, byteorder)
    if num == 1:
        return [[0]]
    else:
        codenum = int.from_bytes(codebytes, byteorder)
        return decode_latin(num, codenum)

total = 0
for i, grid in enumerate(grid_reader(test_data_name), 1):
    #show(grid)
    codebytes = compress(grid)
    length = len(codebytes)
    total += length
    newgrid = decompress(codebytes)
    ok = newgrid == grid
    print('{:>2}: Length = {:>3}, {}'.format(i, length, ok))
    #print('Code:', codebytes)
    #show(newgrid)

print('Total bytes: {}'.format(total))

আউটপুট

 1: Length =   1, True
 2: Length =   1, True
 3: Length =   2, True
 4: Length =   3, True
 5: Length =   5, True
 6: Length =   7, True
 7: Length =  11, True
 8: Length =  14, True
 9: Length =  20, True
10: Length =  26, True
11: Length =  33, True
12: Length =  41, True
13: Length =  50, True
14: Length =  61, True
15: Length =  72, True
16: Length =  84, True
17: Length =  98, True
18: Length = 113, True
19: Length = 129, True
20: Length = 147, True
21: Length = 165, True
22: Length = 185, True
23: Length = 206, True
24: Length = 229, True
25: Length = 252, True
Total bytes: 1955

2

পাইথন 3 - 3,572 3,581 বাইট

from itertools import *
from math import *

def int2base(x,b,alphabet='0123456789abcdefghijklmnopqrstuvwxyz'):
    if isinstance(x,complex):
        return (int2base(x.real,b,alphabet) , int2base(x.imag,b,alphabet))
    if x<=0:
        if x==0:return alphabet[0]
        else:return  '-' + int2base(-x,b,alphabet)
    rets=''
    while x>0:
        x,idx = divmod(x,b)
        rets = alphabet[idx] + rets
    return rets

def lexicographic_index(p):
    result = 0
    for j in range(len(p)):
        k = sum(1 for i in p[j + 1:] if i < p[j])
        result += k * factorial(len(p) - j - 1)
    return result

def getPermutationByindex(sequence, index):
    S = list(sequence)
    permutation = []
    while S != []:
        f = factorial(len(S) - 1)
        i = int(floor(index / f))
        x = S[i]
        index %= f
        permutation.append(x)
        del S[i]
    return tuple(permutation)

alphabet = "abcdefghijklmnopqrstuvwxyz"

def dataCompress(lst):
    n = len(lst[0])

    output = alphabet[n-1]+"|"

    for line in lst:
        output += "%s|" % int2base(lexicographic_index(line), 36)

    return output[:len(output) - 1]

def dataDeCompress(data):
    indexes = data.split("|")
    n = alphabet.index(indexes[0]) + 1
    del indexes[0]

    lst = []

    for index in indexes:
        if index != '':
            lst.append(getPermutationByindex(range(n), int(index, 36)))

    return lst

dataCompress পূর্ণসংখ্যা টিপলগুলির একটি তালিকা নেয় এবং একটি স্ট্রিং প্রদান করে।

dateDeCompress একটি স্ট্রিং নেয় এবং পূর্ণসংখ্যা টিউপসগুলির একটি তালিকা প্রদান করে।

সংক্ষেপে, প্রতিটি লাইনের জন্য, এই প্রোগ্রামটি রেখাগুলি ক্রমশক্তি সূচী নেয় এবং এটি বেস ৩ in এ সংরক্ষণ করে omp

ব্যবহার:

dataCompress([(2,0,1),(1,2,0),(0,1,2)])

ফলাফল: c|4|3|0

dataDeCompress("c|4|3|0")

ফলাফল: [(2, 0, 1), (1, 2, 0), (0, 1, 2)]


2
আপনি যদি permutationsকলগুলিতে আপনার কলটি গুটিয়ে না রাখেন তবে আপনি সম্ভবত আরও অনেক ভাল রানটাইম পেতে চাইবেন list- permutationsএকটি জেনারেটর ফিরিয়ে দেন, যা অলসভাবে সমস্ত অনুমতিগুলি উত্পন্ন করে, তবে আপনি যদি এটির মধ্যে চেষ্টা করার চেষ্টা করেন list, তবে এটি আগ্রহীভাবে সমস্ত অনুমতি তৈরি করে, যা গ্রহণ করে একটি খুব দীর্ঘ সময়.
মেগো

আপনি কীভাবে আপনার কোডটি ব্যবহার করবেন সে সম্পর্কে আরও কিছুটা ব্যাখ্যা করতে পারেন?
মেগো

@ মেগো শিওর, সম্ভবত আমি অলস মূল্যায়নও বাস্তবায়ন করব, যদিও এটি এখনও মোটামুটি আপোনাযোগ্য।
Yytsi



1

জাভা, 2310 বাইট

স্কোয়ারের প্রতিটি সারিটি এমন একটি সংখ্যায় রূপান্তরিত করি যা প্রতিনিধিত্ব করে যে কোন শব্দতাত্ত্বিক ক্রমান্বয়ে এটি ফ্যাকটোরেডিক সংখ্যাগুলি ব্যবহার করছে, এটি একটি ফ্যাকটোরিয়াল সংখ্যা সিস্টেম হিসাবেও পরিচিত , যা ক্রম সংখ্যা নির্ধারণের জন্য দরকারী।

আমরা স্কোয়ারটি বাইনারি ফাইলটিতে লিখি যেখানে প্রথম বাইটটি বর্গক্ষেত্রের আকার এবং তারপরে প্রতিটি সারিতে একটি জাভা বিগইন্টিজারের বাইনারি উপস্থাপনায় বাইটের সংখ্যার জন্য একটি বাইট থাকে, তারপরে সেই বিগইন্টিজারের বাইট থাকে।

প্রক্রিয়াটি বিপরীত করতে এবং স্কোয়ারটি সংক্ষেপিত করতে আমরা মাপটি পিছনে এবং তারপরে প্রতিটি বিগইন্টিজার পড়ি এবং স্কোয়ারের প্রতিটি সারিটি তৈরি করতে সেই সংখ্যাটি ব্যবহার করি।

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Latin {
    public static void main(String[] args) {
        if (args.length != 3) {
            System.out.println("java Latin {-c | -d} infile outfile");
        } else if (args[0].equals("-c")) {
            compress(args[1], args[2]);
        } else if (args[0].equals("-d")) {
            decompress(args[1], args[2]);
        } else {
            throw new IllegalArgumentException(
                "Invalid mode: " + args[0] + ", not -c or -d");
        }
    }

    public static void compress(String filename, String outname) {
        try (BufferedReader br = Files.newBufferedReader(Paths.get(filename))) {
            try (OutputStream os =
                    new BufferedOutputStream(new FileOutputStream(outname))) {
                String line = br.readLine();
                if (line == null) return;
                int size = line.split(",").length;
                if (size > 127) throw new ArithmeticException(
                    "Overflow: square too large");
                Permutor perm = new Permutor(size);
                os.write((byte) size); // write size of square

                do {
                    List<Integer> nums = Arrays.stream(line.split(","))
                        .map(Integer::new)
                        .collect(Collectors.toList());
                    byte[] bits = perm.which(nums).toByteArray();
                    os.write((byte) bits.length); // write length of bigint
                    os.write(bits); // write bits of bigint
                } while ((line = br.readLine()) != null);
            }
        } catch (IOException e) {
            System.out.println("Error compressing " + filename);
            e.printStackTrace();
        }
    }

    public static void decompress(String filename, String outname) {
        try (BufferedInputStream is =
                new BufferedInputStream(new FileInputStream(filename))) {
            try (BufferedWriter bw =
                    Files.newBufferedWriter(Paths.get(outname))) {
                int size = is.read(); // size of latin square
                Permutor perm = new Permutor(size);
                for (int i = 0; i < size; ++i) {
                    int num = is.read(); // number of bytes in bigint
                    if (num == -1) {
                        throw new IOException(
                            "Unexpected end of file reading " + filename);
                    }
                    byte[] buf = new byte[num];
                    int read = is.read(buf); // read bits of bigint into buf
                    if (read != num) {
                        throw new IOException(
                            "Unexpected end of file reading " + filename);
                    }
                    String row = perm.nth(new BigInteger(buf)).stream()
                        .map(Object::toString)
                        .collect(Collectors.joining(","));
                    bw.write(row);
                    bw.newLine();
                }
            }
        } catch (IOException e) {
            System.out.println("Error reading " + filename);
            e.printStackTrace();
        }
    }
}

অনুমতিমূলক কাজ করার জন্য কয়েক বছর আগে আমি যে ক্লাসটি লিখেছিলাম সেখান থেকে অভিযোজকটি অভিযোজিত:

import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.math.BigInteger;
import static java.math.BigInteger.ZERO;
import static java.math.BigInteger.ONE;

public class Permutor {
    private final List<Integer> items;

    public Permutor(int n) {
        items = new ArrayList<>();
        for (int i = 0; i < n; ++i) items.add(i);
    }

    public BigInteger size() {
        return factorial(items.size());
    }

    private BigInteger factorial(int x) {
        BigInteger f = ONE;
        for (int i = 2; i <= x; ++i) {
            f = f.multiply(BigInteger.valueOf(i));
        }
        return f;
    }

    public List<Integer> nth(long n) {
        return nth(BigInteger.valueOf(n));
    }

    public List<Integer> nth(BigInteger n) {
        if (n.compareTo(size()) > 0) {
            throw new IllegalArgumentException("too high");
        }
        n = n.subtract(ONE);
        List<Integer> perm = new ArrayList<>(items);
        int offset = 0, size = perm.size() - 1;
        while (n.compareTo(ZERO) > 0) {
            BigInteger fact = factorial(size);
            BigInteger mult = n.divide(fact);
            n = n.subtract(mult.multiply(fact));
            int pos = mult.intValue();
            Integer t = perm.get(offset + pos);
            perm.remove((int) (offset + pos));
            perm.add(offset, t);
            --size;
            ++offset;
        }
        return perm;
    }

    public BigInteger which(List<Integer> perm) {
        BigInteger n = ONE;
        List<Integer> copy = new ArrayList<>(items);
        int size = copy.size() - 1;
        for (Integer t : perm) {
            int pos = copy.indexOf(t);
            if (pos < 0) throw new IllegalArgumentException("invalid");
            n = n.add(factorial(size).multiply(BigInteger.valueOf(pos)));
            copy.remove((int) pos);
            --size;
        }
        return n;
    }
}

ব্যবহার:

একটি লাতিন বর্গক্ষেত্র সহ latin.txt, এটি সঙ্কুচিত করুন:

java Latin -c latin.txt latin.compressed

এবং এটি সঙ্কুচিত করুন:

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