Dữ liệu thẻ chơi ngẫu nhiên


19

Tôi có dữ liệu thực tôi đang sử dụng cho một trò chơi thẻ mô phỏng. Tôi chỉ quan tâm đến thứ hạng của các thẻ, không phải bộ quần áo. Tuy nhiên, nó là một cỗ bài tiêu chuẩn nên chỉ có cấp bậc trong mỗi bộ bài. Bộ bài được xáo trộn tốt cho mỗi tay, và sau đó tôi xuất toàn bộ bộ bài thành một tập tin. Vì vậy, chỉ có ký tự có thể trong tập tin đầu ra là . ( = mười cấp). Vì vậy, tất nhiên chúng ta có thể bitpack chúng bằng cách sử dụng bit cho mỗi ký hiệu, nhưng sau đó chúng ta đang lãng phí trong số mã hóa có thể. Chúng ta có thể làm tốt hơn nếu chúng ta nhóm biểu tượng cùng một lúc, và sau đó nén chúng, bởi vì4 3 16 4 13 4 28 , 561 15 16 13 2 3.70044 13 52 4 3.2524132,3,4,5,6,7,8,9,T,J,Q,K,AT43164134 = và điều đó có thể phù hợp thay vì "khít" thành bit thay vì . Giới hạn bitpacking lý thuyết là log ( ) / log ( ) = cho dữ liệu với ký hiệu ngẫu nhiên cho mỗi thẻ có thể. Tuy nhiên chúng ta không thể có vị vua chẳng hạn trong bộ bài này. Chúng ta PHẢI chỉ có mỗi cấp bậc trong mỗi bộ bài để mã hóa entropy giảm khoảng một nửa bit cho mỗi ký hiệu xuống còn khoảng .28,56115161323.70044135243.2

Ok, đây là những gì tôi đang nghĩ. Dữ liệu này không hoàn toàn ngẫu nhiên. Chúng tôi biết có cấp bậc cho mỗi cấp bậc trong mỗi khối gồm thẻ (gọi đó là một cỗ bài xáo trộn), vì vậy chúng tôi có thể đưa ra một số giả định và tối ưu hóa. Một trong những người chúng ta không phải mã hóa thẻ cuối cùng, bởi vì chúng ta sẽ biết nó nên là gì. Một khoản tiết kiệm khác sẽ là nếu chúng ta kết thúc trên một cấp bậc duy nhất; ví dụ: nếu thẻ cuối cùng trong bộ bài là , chúng tôi sẽ không phải mã hóa chúng vì bộ giải mã sẽ đếm các thẻ đến thời điểm đó và thấy rằng tất cả các cấp bậc khác đã được điền và sẽ giả sử " thiếu "thẻ là tất cả s.52 3 777 3 7452377737

Vì vậy, câu hỏi của tôi cho trang web này là, những tối ưu hóa nào khác có thể có được một tệp đầu ra thậm chí nhỏ hơn trên loại dữ liệu này và nếu chúng ta sử dụng chúng, chúng ta có thể đánh bại entropy bitpacking lý thuyết (đơn giản) là bit cho mỗi ký hiệu hay không thậm chí tiếp cận giới hạn entropy cuối cùng trung bình khoảng bit cho mỗi ký hiệu? Nếu vậy thì thế nào?3.23.700443.2

Khi tôi sử dụng chương trình loại ZIP (ví dụ WinZip), tôi chỉ thấy khoảng nén , cho tôi biết nó chỉ đang thực hiện một bitpack "lười biếng" thành bit. Nếu tôi "nén trước" dữ liệu bằng cách sử dụng bitpack của riêng mình, thì có vẻ như điều đó tốt hơn, bởi vì khi tôi chạy nó thông qua chương trình zip, tôi sẽ bị nén hơn . Những gì tôi đang nghĩ là, tại sao không tự mình thực hiện việc nén (vì tôi có nhiều kiến ​​thức về dữ liệu hơn chương trình Zip). Tôi tự hỏi nếu tôi có thể đánh bại "giới hạn" entropy của log ( ) / log ( ) =4 2 : 1 13 2 3.700442:142:11323.70044. Tôi nghi ngờ tôi có thể với một vài "thủ thuật" mà tôi đã đề cập và một vài điều nữa tôi có thể tìm ra. Các tập tin đầu ra tất nhiên không phải là "con người có thể đọc được". Miễn là mã hóa là lossless, nó là hợp lệ.

Dưới đây là một liên kết đến triệu sàn xáo trộn có thể đọc được của con người ( trên mỗi dòng). Bất cứ ai cũng có thể "thực hành" trên một tập hợp con nhỏ của các dòng này và sau đó cho phép nó trích xuất trên toàn bộ tệp. Tôi sẽ tiếp tục cập nhật kích thước tệp tốt nhất (nhỏ nhất) dựa trên dữ liệu này.131

https://drive.google.com/file/d/0BweDAVsuCEM1amhsNmFITnEwd2s/view

Nhân tiện, trong trường hợp bạn quan tâm đến loại trò chơi bài này, dữ liệu này được sử dụng cho mục đích gì, đây là liên kết đến câu hỏi hoạt động của tôi (với tiền thưởng điểm). Tôi được cho biết đây là một vấn đề khó giải quyết (chính xác) vì nó sẽ cần một lượng không gian lưu trữ dữ liệu rất lớn. Một số mô phỏng đồng ý với xác suất gần đúng mặc dù. Không có giải pháp toán học thuần túy nào được cung cấp (chưa). Nó quá khó, tôi đoán vậy.300

/math/1882705/probability-2-player-card-game-with-multipl-potypes-to-win-who-has-the-THER

Tôi có một thuật toán tốt là hiển thị bit để mã hóa bộ bài đầu tiên trong dữ liệu mẫu của tôi. Dữ liệu này được tạo ngẫu nhiên bằng thuật toán xáo trộn Fisher-Yates. Đó là dữ liệu ngẫu nhiên thực sự, vì vậy thuật toán mới được tạo của tôi dường như đang hoạt động RẤT tốt, điều này làm tôi hài lòng.168

Liên quan đến "thử thách" nén, tôi hiện đang ở mức khoảng 160 bit cho mỗi bộ bài. Tôi nghĩ rằng tôi có thể giảm xuống có thể 158. Có tôi đã thử và tôi đã nhận được 158,43 bit mỗi sàn. Tôi nghĩ rằng tôi đang tiến gần đến giới hạn của thuật toán của mình nên tôi đã thành công khi giảm xuống dưới 166 bit trên mỗi bộ bài nhưng tôi đã không nhận được 156 bit sẽ là 3 bit cho mỗi thẻ nhưng đó là một bài tập thú vị. Có lẽ trong tương lai tôi sẽ nghĩ ra một cái gì đó để giảm trung bình mỗi bộ bài trung bình từ 2,43 bit trở lên.


8
Nếu bạn tự tạo các cỗ bài xáo trộn này (chứ không phải mô tả trạng thái của cỗ bài vật lý chẳng hạn), bạn hoàn toàn không cần lưu trữ cỗ bài - chỉ cần lưu trữ hạt giống RNG tạo ra cỗ bài.
jasonharper

3
Mô tả của bạn và những câu trả lời rất giống với một khái niệm thường được gọi là mã hóa phạm vi ( en.wikipedia.org/wiki/Range_encoding ). Bạn điều chỉnh các mức độ phù hợp sau mỗi thẻ để nó phản ánh các thẻ còn lại có thể.
H. I đột ngột

Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


3

Một điều khác cần xem xét: nếu bạn chỉ quan tâm đến việc nén một bộ đầy đủ vài triệu sàn và bạn cũng không quan tâm đến thứ tự của chúng, bạn có thể có được tính linh hoạt mã hóa bổ sung bằng cách loại bỏ thông tin về thứ tự của bộ sàn . Ví dụ, đây sẽ là trường hợp nếu bạn cần tải tập hợp để liệt kê tất cả các sàn và xử lý chúng, nhưng không quan tâm chúng được xử lý theo thứ tự nào.

Bạn bắt đầu bằng cách mã hóa từng bộ bài riêng lẻ, vì các câu trả lời khác đã mô tả cách thực hiện. Sau đó, sắp xếp các giá trị được mã hóa. Lưu trữ một loạt các khác biệt giữa các giá trị được mã hóa được sắp xếp (trong đó sự khác biệt đầu tiên bắt đầu từ sàn được mã hóa '0'). Với một số lượng lớn các sàn, sự khác biệt sẽ có xu hướng nhỏ hơn phạm vi mã hóa đầy đủ, vì vậy bạn có thể sử dụng một số hình thức mã hóa varint để xử lý các khác biệt lớn thường xuyên trong khi vẫn lưu trữ các khác biệt nhỏ hơn một cách hiệu quả. Lược đồ varint thích hợp sẽ phụ thuộc vào số lượng sàn bạn có trong tập hợp (do đó xác định kích thước chênh lệch trung bình.)

Thật không may, tôi không biết toán học về việc điều này sẽ giúp bạn nén được bao nhiêu, nhưng nghĩ rằng ý tưởng này có thể hữu ích để xem xét.


1
Nói một cách đại khái, nếu bạn có vài triệu sàn ngẫu nhiên thì sự khác biệt trung bình sẽ là một (vài phần triệu) của phạm vi đầy đủ, nghĩa là bạn sẽ tiết kiệm được khoảng 20 bit cho mỗi giá trị. Bạn mất một chút cho mã hóa varint của bạn.
Steve Jessop

2
@DavidJames: nếu thứ tự cụ thể của các sàn không quan trọng, chỉ là không có sai lệch trong đó, bạn có thể xáo trộn lại 3 triệu sàn sau khi giải nén (nghĩa là không thay đổi bất kỳ sàn nào, chỉ cần thay đổi thứ tự danh sách 3 triệu sàn).
Steve Jessop

2
Đây chỉ là một cách để giảm nội dung thông tin thêm một chút nếu thông tin đặt hàng không quan trọng; nếu nó quan trọng, điều này không thể áp dụng và có thể bỏ qua. Điều đó nói rằng, nếu tầm quan trọng duy nhất đối với thứ tự của bộ sàn là 'ngẫu nhiên', bạn chỉ có thể chọn ngẫu nhiên thứ tự sau khi giải nén, như @SteveJessop đã nêu.
Dan Bryant

@DavidJames Thấy rằng 173 sàn đầu tiên của bạn bắt đầu bằng KKKK, và không nhìn vào vài triệu người khác, và kết luận rằng tất cả đều bắt đầu với KKKK, là một điều khá ngu ngốc. Đặc biệt là nếu chúng rõ ràng là theo thứ tự sắp xếp.
dùng253751

3
@DavidJames: dữ liệu này được nén và thói quen giải nén có thể tái ngẫu nhiên hóa nó nếu muốn. "Một người ngây thơ" sẽ không nhận được bất cứ điều gì cả, thậm chí họ sẽ không tìm ra cách diễn giải nó như những cỗ bài. Đó không phải là một lỗ hổng trong định dạng lưu trữ dữ liệu (trong trường hợp này là định dạng mất dữ liệu), rằng ai đó sử dụng nó cần RTFM để lấy ra dữ liệu phù hợp.
Steve Jessop

34

Đây là một thuật toán hoàn chỉnh đạt đến giới hạn lý thuyết.

Mở đầu: Mã hóa chuỗi số nguyên

Một số nguyên gồm 13 số nguyên "số nguyên có giới hạn trên , số nguyên có giới hạn trên b - 1 ," số nguyên có giới hạn trên c - 1 , số nguyên có giới hạn trên d - 1 , ... số nguyên có giới hạn trên m - 1 " luôn luôn có thể được mã hóa với hiệu quả hoàn hảo.một-1b-1c-1d-1m-1

  1. Lấy số nguyên đầu tiên, nhân số đó với , thêm số thứ hai, nhân kết quả với c , thêm số thứ ba, nhân kết quả với d , Chuyện nhân kết quả với m , thêm số thứ ba - và điều đó sẽ tạo ra một số duy nhất trong khoảng 0a b c d e f g h i j k l m - 1 .bcdm0mộtbcdefghtôijktôim-1
  2. Viết số đó vào nhị phân.

Điều ngược lại cũng dễ dàng. Chia cho và phần còn lại là số nguyên thứ mười ba. Chia kết quả cho l và phần còn lại là số nguyên thứ mười hai. Tiếp tục cho đến khi bạn chia cho b : phần còn lại là số nguyên thứ hai và thương số là số nguyên đầu tiên.mtôib

Vì vậy, để mã hóa thẻ của bạn theo cách tốt nhất có thể, tất cả những gì chúng ta phải làm là tìm một sự tương ứng hoàn hảo giữa các chuỗi 13 số nguyên (với các giới hạn trên) và cách sắp xếp các thẻ được xáo trộn của bạn.

Đây là cách làm.

Sự tương ứng giữa xáo trộn và chuỗi số nguyên

Bắt đầu với một chuỗi 0 thẻ trên bàn trước mặt bạn.

Bước 1

Lấy bốn số 2 trong gói của bạn và đặt chúng trên bàn.

Bạn có lựa chọn nào? Thẻ hoặc thẻ có thể được đặt ở đầu chuỗi đã có trên bàn hoặc sau bất kỳ một trong các thẻ trong chuỗi đó. Trong trường hợp đó, điều này có nghĩa là có nơi có thể để đặt thẻ.1+0= =1

Tổng số cách đặt 4 thẻ ở 1 vị trí là . Mã hóa từng cách đó dưới dạng một số trong khoảng từ 0 đến 1 - 1 . Có 1 số như vậy.101-1

Tôi đã nhận được 1 bằng cách xem các cách viết 0 là tổng của 5 số nguyên: đó là .4×3×2×14!

Bước 2

Lấy bốn số 3 trong gói của bạn và đặt chúng trên bàn.

Bạn có lựa chọn nào? Thẻ hoặc thẻ có thể được đặt ở đầu chuỗi đã có trên bàn hoặc sau bất kỳ một trong các thẻ trong chuỗi đó. Trong trường hợp đó, điều này có nghĩa là có nơi có thể đặt thẻ.1+4= =5

Tổng số cách đặt 4 thẻ ở 5 vị trí là . Mã hóa từng cách theo một số trong khoảng từ 0 đến 70 - 1 . Có 70 con số như vậy.70070-1

Tôi đã nhận được 70 bằng cách xem cách viết 4 là tổng của 5 số nguyên: đó là .số 8×7×6×54!

Bước 3

Lấy bốn 4s trong gói của bạn và đặt chúng trên bàn.

Bạn có lựa chọn nào? Thẻ hoặc thẻ có thể được đặt ở đầu chuỗi đã có trên bàn hoặc sau bất kỳ một trong các thẻ trong chuỗi đó. Trong trường hợp đó, điều này có nghĩa là có vị trí có thể đặt thẻ.1+số 8= =9

Tổng số cách đặt 4 thẻ ở 9 vị trí là . Mã hóa từng cách theo một số trong khoảng từ 0 đến 495 - 1 . Có 495 con số như vậy.4950495-1

Tôi đã nhận được 495 bằng cách xem cách viết 8 là tổng của 5 số nguyên: đó là .12×11×10×94!

Và cứ thế, cho đến khi ...

Bước 13

Lấy bốn con át trong gói của bạn và đặt chúng trên bàn.

Bạn có lựa chọn nào? Thẻ hoặc thẻ có thể được đặt ở đầu chuỗi đã có trên bàn hoặc sau bất kỳ một trong các thẻ trong chuỗi đó. Trong trường hợp đó, điều này có nghĩa là có địa điểm có thể để đặt thẻ.1+48= =49

Tổng số cách đặt 4 thẻ ở 49 vị trí là . Mã hóa từng cách đó dưới dạng một số trong khoảng từ 0 đến 270725 - 1 . Có 270725 số như vậy.2707250270725-1

Tôi đã nhận được 270725 bằng cách xem cách viết 48 là tổng của 5 số nguyên: đó là .52×51×50×494!


Thủ tục này mang lại một 1-to-1 tương ứng giữa (a) shufflings thẻ mà bạn không quan tâm đến những bộ đồ và (b) chuỗi các số nguyên nơi đầu tiên là giữa 1 - 1 , thứ hai là giữa 070 - 1 , thứ ba là từ 0 đến 495 - 1 , và cứ như vậy cho đến ngày mười ba, nằm trong khoảng từ 0 đến 270725 - 1 .01-1070-10495-10270725-1

Đề cập đến "Encoding chuỗi số nguyên", bạn có thể thấy rằng một chuỗi như các số nguyên là trong 1-1 tương ứng với số giữa ( 1 × 70 × 495 × ... × 270.725 ) - 1 . Nếu bạn nhìn vào biểu thức "sản phẩm chia cho một giai thừa" của mỗi số nguyên ( như được mô tả bằng chữ in nghiêng ở cuối mỗi bước ) thì bạn sẽ thấy rằng điều này có nghĩa là các số từ 0 đến 52 !0(1×70×495×Giáo dục×270725)-10mà câu trả lời trước đây của tôi cho thấy là tốt nhất có thể.

52!(4!)13-1,

Vì vậy, chúng tôi có một phương pháp hoàn hảo để nén thẻ xáo trộn của bạn.


Thuật toán

Tính toán trước một danh sách tất cả các cách viết 0 là tổng của 5 số nguyên, viết 4 là tổng của 5 số nguyên, viết 8 là tổng của 5 số nguyên, cách viết 48 là tổng của 5 số nguyên. Danh sách dài nhất có 270725 phần tử, vì vậy nó không đặc biệt lớn. (Tính toán trước không thực sự cần thiết vì bạn có thể dễ dàng tổng hợp từng danh sách và khi bạn cần: thử với Microsoft QuickBasic, thậm chí đi qua danh sách 270725 yếu tố nhanh hơn mắt có thể thấy)

Để chuyển từ xáo trộn sang một chuỗi các số nguyên:

2s không đóng góp gì, vì vậy hãy bỏ qua chúng. Viết một số từ 0 đến 1-1.

3s: Có bao nhiêu 2 giây trước 3 đầu tiên? Có bao nhiêu trước lần thứ hai? người thứ ba? Hạng 4? Sau lần thứ 4? Câu trả lời là 5 số nguyên rõ ràng cộng tới 4. Vì vậy, hãy tìm chuỗi 5 số nguyên đó trong danh sách "viết 4 là tổng của 5 số nguyên" và lưu ý vị trí của nó trong danh sách đó. Đó sẽ là một số trong khoảng từ 0 đến 70-1. Viết nó xuống.

Các 4s: Có bao nhiêu 2 hoặc 3 giây trước 4 đầu tiên? Có bao nhiêu trước lần thứ hai? người thứ ba? Hạng 4? Sau lần thứ 4? Câu trả lời là 5 số nguyên rõ ràng cộng tới 8. Vì vậy, hãy tìm chuỗi 5 số nguyên đó trong danh sách "viết 8 là tổng của 5 số nguyên" và lưu ý vị trí của nó trong danh sách đó. Đó sẽ là một số trong khoảng từ 0 đến 495-1. Viết nó xuống.

Cứ như vậy, cho đến khi đạt được

Những con át chủ bài: Có bao nhiêu thẻ không phải là ace trước khi ace đầu tiên? Có bao nhiêu trước lần thứ hai? người thứ ba? Hạng 4? Sau lần thứ 4? Câu trả lời là 5 số nguyên rõ ràng cộng tới 48. Vì vậy, hãy tìm chuỗi 5 số nguyên đó trong danh sách "viết 48 là tổng của 5 số nguyên" và lưu ý vị trí của nó trong danh sách đó. Đó sẽ là một số trong khoảng từ 0 đến 270725-1. Viết nó xuống.

Bây giờ bạn đã viết ra 13 số nguyên. Mã hóa chúng (như được mô tả trước đây) thành một số duy nhất trong khoảng từ đến 52 !0 . Viết số đó ra dưới dạng nhị phân. Nó sẽ chỉ mất dưới 166 bit.52!(4!)13

Đây là nén tốt nhất có thể, bởi vì nó đạt đến giới hạn lý thuyết thông tin.

Giải nén rất đơn giản: đi từ số lớn đến chuỗi 13 số nguyên, sau đó sử dụng chúng để xây dựng chuỗi thẻ như đã mô tả.


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
DW

Giải pháp này không rõ ràng với tôi và không đầy đủ. Nó không chỉ ra làm thế nào để thực sự có được số 166 bit và giải mã nó trở lại vào cỗ bài. Không dễ dàng gì để thụ thai cho tôi vì vậy tôi không biết làm thế nào để thực hiện nó. Công thức bước của bạn về cơ bản chỉ cần tách công thức thành 13 phần thực sự không giúp tôi nhiều. Tôi nghĩ rằng nó sẽ có ích nếu bạn lập một sơ đồ hoặc biểu đồ cho bước 2 có thể với 70 cách có thể để sắp xếp các thẻ. Giải pháp của bạn quá trừu tượng để bộ não của tôi chấp nhận và xử lý. Tôi thích các ví dụ thực tế và minh họa. 52!/(4!13)13
David James

23

Thay vì cố gắng mã hóa từng thẻ riêng biệt thành 3 hoặc 4 bit, tôi khuyên bạn nên mã hóa trạng thái của toàn bộ boong thành 166 bit. Như Martin Kochanski giải thích , có ít hơn sắp xếp các thẻ bỏ qua các bộ quần áo, vì vậy điều đó có nghĩa là trạng thái của toàn bộ cỗ bài có thể được lưu trữ trong 166 bit.2166

Làm thế nào để bạn thực hiện việc nén và giải nén này theo thuật toán, một cách hiệu quả? Tôi đề nghị sử dụng thứ tự từ điển và tìm kiếm nhị phân. Điều này sẽ cho phép bạn thực hiện nén và giải nén hiệu quả (cả về không gian và thời gian), mà không yêu cầu bảng tra cứu lớn hoặc các giả định không thực tế khác.

Chi tiết hơn: Hãy sắp xếp các sàn bằng cách sử dụng thứ tự từ vựng trên biểu diễn không nén của sàn, tức là một sàn được biểu diễn dưới dạng không nén dưới dạng một chuỗi như 22223333444455556666777788889999TTTTJJJJQQQQKKKKAAAA; bạn có thể đặt chúng theo thứ tự từ điển. Bây giờ, giả sử bạn có một quy trình đưa ra một sàn , đếm số lượng các sàn đến trước nó (theo thứ tự từ điển). Sau đó, bạn có thể sử dụng quy trình này để nén một bộ bài: với một bộ bài D , bạn nén một số 166 bit bằng cách đếm số bộ bài đi trước nó và sau đó xuất ra số đó. Con số đó là đại diện nén của bộ bài.DD

Để giải nén, sử dụng tìm kiếm nhị phân. Cho một số , bạn muốn tìm bộ bài thứ n theo thứ tự từ điển của tất cả các bộ bài. Bạn có thể thực hiện việc này bằng cách sử dụng quy trình dọc theo dòng tìm kiếm nhị phân: chọn một sàn D 0 , đếm số sàn trước D 0 và so sánh với n . Điều đó sẽ cho bạn biết có nên điều chỉnh D 0 khôngnnD0D0nD0đến sớm hơn hoặc muộn hơn Tôi khuyên bạn nên thử lặp lại biểu tượng đúng: nếu bạn muốn khôi phục một chuỗi như 22223333444455556666777788889999TTTTJJJJQQQQKKKKAAAA, trước tiên hãy tìm kiếm những gì sẽ sử dụng làm biểu tượng đầu tiên trong chuỗi ), sau đó khi bạn tìm thấy giá trị phù hợp cho biểu tượng đầu tiên, hãy tìm kiếm để tìm biểu tượng thứ hai, v.v.

Tất cả những gì còn lại là để đưa ra một quy trình hiệu quả để đếm số lượng các sàn mà đến thứ tự từ điển trước khi . Điều này trông giống như một bài tập tổ hợp đơn giản nhưng tẻ nhạt. Cụ thể, tôi khuyên bạn nên xây dựng một chương trình con cho vấn đề sau: đưa ra một tiền tố (như 222234), đếm số sàn bắt đầu với tiền tố đó. Câu trả lời cho vấn đề này có vẻ như là một bài tập khá dễ dàng trong các hệ số nhị thức và giai thừa. Sau đó, bạn có thể gọi chương trình con này một số ít lần để đếm số lượng các sàn mà đến trước D .DD


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
DW

8

Số lượng sắp xếp có thể của các thẻ bỏ qua phù hợpcó logarit cơ sở 2 là 165.976, hoặc 3.1919 bit trên mỗi thẻ, tốt hơn giới hạn bạn đưa ra.

52!(4!)13,

Bất kỳ mã hóa "bit trên mỗi thẻ" cố định sẽ không có ý nghĩa bởi vì, như bạn lưu ý, thẻ cuối cùng luôn có thể được mã hóa thành bit và trong nhiều trường hợp, một vài thẻ cuối cùng cũng có thể như vậy. Điều đó có nghĩa là đối với "đuôi" của gói, số bit cần thiết cho mỗi thẻ sẽ ít hơn rất nhiều so với bạn nghĩ.0

Cho đến nay, cách tốt nhất để nén dữ liệu là tìm 59 bit dữ liệu khác mà bạn muốn đóng gói với dữ liệu thẻ của mình (thực tế là 59,6 bit) và, viết 59 bit đó dưới dạng modulo 24 chữ số 24 (= ), chuyển nhượng một bộ đồ để mỗi thẻ (người ta chọn chữ số giữa 4 ! cách gán phù hợp với con át chủ bài, khác cũng làm như vậy cho các vua, và vân vân). Sau đó, bạn có một gói gồm 52 thẻ hoàn toàn khác nhau. 52 ! khả năng có thể được mã hóa trong 225,58 bit thực sự rất dễ dàng.4!4!52!

Nhưng làm điều đó mà không tận dụng cơ hội mã hóa các bit thừa đó cũng có thể ở một mức độ nào đó, và tôi sẽ nghĩ về nó vì tôi chắc chắn rằng mọi người khác đều như vậy. Cảm ơn bạn cho một vấn đề thực sự thú vị!


1
Có thể sử dụng một cách tiếp cận tương tự như ăn cắp mật mã ở đây? Như trong, dữ liệu bạn mã hóa trong 59 bit bổ sung đó có phải là 59 bit cuối cùng của biểu diễn được mã hóa không?
John Dvorak

@JanD Tôi đã suy nghĩ về việc điều tra một cái gì đó như thế này. Nhưng sau đó hóa ra là một thuật toán tồn tại đạt đến giới hạn lý thuyết và đơn giản và đáng tin cậy 100%, vì vậy không có lý do gì để tìm kiếm thêm.
Martin Kochanski

@MartinKochanski - Tôi sẽ không gọi nó là "bỏ qua bộ quần áo" vì chúng tôi vẫn đang tôn vinh 4 bộ đồ tiêu chuẩn cho mỗi cấp bậc. Từ ngữ tốt hơn có thể là "Số lượng sắp xếp khác biệt có thể có của bộ bài là" ...
David James

3

Đây là một vấn đề giải quyết lâu dài.

Khi bạn giao dịch một bộ gồm 52 thẻ, mỗi thẻ bạn giao dịch có một trong số 13 cấp bậc với xác suất được biết đến. Xác suất thay đổi với mỗi giao dịch thẻ. Điều đó được xử lý tối ưu bằng cách sử dụng một kỹ thuật cổ xưa gọi là mã hóa số học thích ứng, một cải tiến cho mã hóa Huffman. Thông thường, nó được sử dụng cho các xác suất đã biết, không thay đổi, nhưng nó cũng có thể được sử dụng để thay đổi xác suất. Đọc bài viết trên wikipedia về mã hóa số học:

https://en.wikipedia.org/wiki/Arithatures_coding


Được rồi nhưng điều này không trả lời câu hỏi của tôi nếu nó có thể tiếp cận, khớp hoặc vượt qua giới hạn mã hóa entropy lý thuyết. Dường như có n sàn có thể có xác suất 1 / n, nên mã hóa entropy là giới hạn và chúng ta không thể làm tốt hơn (trừ khi chúng ta "gian lận" và nói với bộ giải mã một số thứ về dữ liệu đầu vào cho bộ mã hóa trước thời hạn.
David James

3

Cả DW và Martin Kochanski đều đã mô tả các thuật toán để xây dựng một sự lựa chọn giữa các giao dịch và số nguyên trong phạm vi , nhưng có vẻ như cả hai đều không giảm vấn đề xuống dạng đơn giản nhất. (Lưu ý 1)[0,52!(4!)13)

Giả sử chúng ta có một cỗ bài (một phần) được mô tả bởi danh sách được sắp xếp , trong đó a i là số lượng thẻ loại i . Trong OP, bộ bài ban đầu được mô tả bởi một danh sách gồm 13 phần tử, mỗi phần tử có giá trị 4. Số lần xáo trộn riêng biệt của bộ bài như vậy làmộtmộttôitôi

c(một)= =(Σmộttôi)!Πmộttôi!

đó là một khái quát đơn giản của các hệ số nhị thức, và thực sự có thể được chứng minh bằng cách đơn giản sắp xếp các đối tượng một loại tại một thời điểm, như đề xuất của Martin Kochanski. (Xem bên dưới, ghi chú 2)

Bây giờ, đối với bất kỳ bộ bài (một phần) nào như vậy, chúng ta có thể chọn xáo trộn một thẻ một lần, sử dụng bất kỳ nào i > 0 . Số lần xáo trộn duy nhất bắt đầu bằng itôimộttôi>0tôi

{0nếu mộttôi= =0c(một1,...,mộttôi-1,mộttôi-1,mộttôi+1,...,mộtn)nếu mộttôi>0.

và theo công thức trên, chúng ta có

c(một1,...,mộttôi-1,mộttôi-1,mộttôi+1,...,mộtn)= =mộttôic(một)Σmộttôi

Sau đó chúng tôi có thể recurse (hoặc lặp) thông qua boong tàu cho đến khi shuffle hoàn tất bằng cách quan sát rằng số lượng shuffles tương ứng với một tiền tố tự từ điển nhỏ hơn so với tiền tố lên tới tôi

c(một)Σj= =1tôimộtjΣj= =1nmộtj

Tôi đã viết điều này bằng Python để minh họa thuật toán; Python là mã giả hợp lý như bất kỳ. Lưu ý rằng hầu hết các số học liên quan đến độ chính xác mở rộng; các giá trị (đại diện cho thứ tự xáo trộn) và n (tổng số lần xáo trộn có thể có cho bộ phận một phần còn lại) đều là bignums 166 bit. Để dịch mã sang ngôn ngữ khác, sẽ cần phải sử dụng một số loại thư viện bignum.kn

Ngoài ra, tôi chỉ sử dụng danh sách các số nguyên thay vì tên thẻ và - không giống như các phép toán ở trên - các số nguyên dựa trên 0.

Để mã hóa xáo trộn, chúng tôi đi qua xáo trộn, tích lũy tại mỗi điểm số lượng xáo trộn bắt đầu bằng một thẻ nhỏ hơn bằng cách sử dụng công thức trên:

from math import factorial
T = factorial(52) // factorial(4) ** 13

def encode(vec):
    a = [4] * 13
    cards = sum(a)
    n = T
    k = 0
    for idx in vec:
        k += sum(a[:idx]) * n // cards
        n = a[idx] * n // cards
        a[idx] -= 1
        cards -= 1
    return k

Giải mã một số 166 bit là nghịch đảo đơn giản. Ở mỗi bước, chúng tôi có mô tả về một bộ phận và một thứ tự; chúng ta cần bỏ qua các xáo trộn bắt đầu bằng các thẻ nhỏ hơn các thẻ tương ứng với thứ tự, và sau đó chúng ta tính toán đầu ra của thẻ đã chọn, xóa nó khỏi bộ bài còn lại và điều chỉnh số lần xáo trộn có thể với tiền tố đã chọn:

def decode(k):
    vec = []
    a = [4] * 13
    cards = sum(a)
    n = T
    while cards > 0:
        i = cards * k // n
        accum = 0
        for idx in range(len(a)):
            if i < accum + a[idx]:
                k -= accum * n // cards
                n = a[idx] * n // cards
                a[idx] -= 1
                vec.append(idx)
                break
            accum += a[idx]
        cards -= 1
    return vec

Tôi đã không thực sự cố gắng để tối ưu hóa mã trên. Tôi đã chạy nó với toàn bộ tệp 3mil.TXT, kiểm tra xem encode(decode(line))kết quả có được mã hóa ban đầu không; nó chỉ mất dưới 300 giây. (Bảy trong số các dòng có thể được nhìn thấy trong bài kiểm tra trực tuyến trên ideone .) Viết lại bằng ngôn ngữ cấp thấp hơn và tối ưu hóa phân chia (có thể) có thể sẽ giảm thời gian đó xuống mức có thể quản lý được.

Vì giá trị được mã hóa chỉ đơn giản là một số nguyên, nên nó có thể được xuất ra trong 166 bit. Không có giá trị trong việc xóa các số 0 đứng đầu, vì khi đó sẽ không có cách nào để biết nơi mã hóa bị chấm dứt, vì vậy nó thực sự là một mã hóa 166 bit.

Tuy nhiên, đáng chú ý là trong một ứng dụng thực tế, có lẽ không bao giờ cần phải mã hóa một shuffle; một shuffle ngẫu nhiên có thể được tạo bằng cách tạo một số 166 bit ngẫu nhiên và giải mã nó. Và không thực sự cần thiết rằng tất cả 166 bit là ngẫu nhiên; ví dụ, có thể bắt đầu bằng số nguyên ngẫu nhiên 32 bit và sau đó điền vào 166 bit bằng cách sử dụng bất kỳ RNG tiêu chuẩn nào được gieo bằng số 32 bit. Vì vậy, nếu mục tiêu chỉ đơn giản là có thể lưu trữ một cách ngẫu nhiên một số lượng lớn các lần xáo trộn ngẫu nhiên, bạn có thể giảm yêu cầu lưu trữ trên mỗi giao dịch ít nhiều tùy ý.

Nếu bạn muốn mã hóa một số lượng lớn N của giao dịch thực tế (được tạo ra trong một số thời trang khác) nhưng không quan tâm đến thứ tự của các giao dịch, bạn có thể đồng bằng mã hóa danh sách được sắp xếp số, tiết kiệm khoảng bit cho mỗi con số. (Kết quả tiết kiệm từ thực tế là một chuỗi được sắp xếp có ít entropy hơn một chuỗi chưa được sắp xếp. Nó không làm giảm entropy của một giá trị trong chuỗi.)đăng nhập2N

Giả sử rằng chúng ta cần mã hóa một danh sách sắp xếp các số k -bit, chúng ta có thể tiến hành như sau:N k

  1. Chọn là số nguyên gần với log 2 N (sàn hoặc trần sẽ hoạt động; tôi thường đi trần).pđăng nhập2N

  2. Chúng tôi ngầm chia phạm vi số thành các khoảng tiền tố nhị phân. Mỗi k số bit được chia thành một p -bit tiền tố và k - p -bit hậu tố; chúng tôi chỉ viết ra các hậu tố (theo thứ tự). Điều này đòi hỏi các bit N ( k - p ) .2pkpk-pN*(k-p)

  3. Ngoài ra, chúng tôi tạo một chuỗi bit: Với mỗi tiền tố (ngoại trừ tiền tố 0 ), chúng tôi viết ra 0 cho mỗi số có tiền tố đó (nếu có) theo sau là 1 . Chuỗi này rõ ràng có 2 bit p + N : 2 p 1 s và N 0 s.2p0012p+N2p 1N 0

Để giải mã các số, chúng tôi bắt đầu bộ đếm tiền tố ở 0 và tiến hành làm việc thông qua chuỗi bit. Khi chúng tôi thấy , chúng tôi xuất tiền tố hiện tại và hậu tố tiếp theo từ danh sách hậu tố; khi chúng ta thấy 1 , chúng ta tăng tiền tố hiện tại.01

Tổng chiều dài của mã hóa là rất gần với N ( k - p ) + N + N , hoặc N ( k - p + 2 ) , trung bình củaN*(k-p)+N+2pN*(k-p)+N+NN*(k-p+2) bit trên mỗi giá trị.k-p+2

Ghi chú

  1. 92024242230271040357108320801872044844750000000000đăng nhập252!(4!)13920242422302710403571083208018720448447500000000000000 là khoảng165,9765đăng nhập252!(4!)13165.9765 . Trong văn bản, tôi thỉnh thoảng giả vờ rằng logarit cơ sở 2 thực sự là ; trong trường hợp tạo các số ngẫu nhiên trong phạm vi, thuật toán loại bỏ có thể được sử dụng mà rất hiếm khi từ chối một số ngẫu nhiên được tạo.166
  2. Để thuận tiện, tôi viết cho n i = k a i ; thì một 1 đối tượng thuộc loại 1 có thể được đặt trong (SkΣtôi= =knmộttôimột11cách, và sau đó các đối tượng của loại2có thể được đặt trong((S1một1)2cách, v.v. Vì ((S2một2), dẫn đến tổng số(Stôimộttôi)= =Stôi!mộttôi!(Stôi-mộttôi)!= =Stôi!mộttôi!Stôi+1!

Πtôi= =1nStôi!Πtôi= =1nmộttôi!Stôi+1!

mà đơn giản hóa công thức trên.


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
DW

@rici - Tôi đã đưa cho bạn số tiền thưởng +100 mà bạn đã giải thích câu trả lời của mình bằng cách trình bày tốt hơn bao gồm cả mã trong khi các câu trả lời khác trừu tượng / lý thuyết hơn, bỏ qua một số chi tiết về cách thực hiện mã hóa / giải mã. Như bạn có thể biết, có nhiều chi tiết khi viết mã. Tôi thừa nhận thuật toán của tôi không phải là đơn giản nhất, đơn giản, dễ hiểu nhưng tôi thực sự đã làm cho nó hoạt động mà không cần nhiều nỗ lực và theo thời gian tôi có thể làm cho nó chạy nhanh hơn với nhiều nén hơn. Vì vậy, cảm ơn câu trả lời của bạn và tiếp tục công việc tốt.
David James

2

Là một giải pháp thay thế cho vấn đề này, thuật toán của tôi sử dụng các bit phân đoạn (không nguyên) cho mỗi thẻ cho các nhóm thẻ trong bộ bài dựa trên số lượng còn lại chưa được xếp hạng. Nó là một thuật toán khá thanh lịch. Tôi đã kiểm tra thuật toán mã hóa của mình bằng tay và nó có vẻ tốt. Bộ mã hóa đang xuất ra những gì có vẻ là bitstrings chính xác (ở dạng byte để đơn giản).

Tổng quan về thuật toán của tôi là nó sử dụng kết hợp các nhóm thẻ và mã hóa bit phân đoạn hỗn hợp. Ví dụ, trong tập tin thử nghiệm chia sẻ của tôi về triệu sàn xáo trộn, người đầu tiên có người đầu tiên 7 thẻ của 54 Một 236 J . Lý do tôi chọn kích thước khối 7 thẻ khi có thể xếp hạng 13 thẻ là vì 13 7 "dây giày" (vừa khít) thành 26 bit (kể từ 13 7 = 62 , 748 , 5172 26 = 67 , 108 ,3754Một236J7131372613762,748,51722667,108,864). Lý tưởng nhất là chúng tôi muốn số đó càng gần càng tốt (nhưng với công suất của 2 số cao hơn một chút) vì vậy chúng tôi không lãng phí nhiều hơn một phần rất nhỏ của một chút trong quy trình đóng gói bit. Lưu ý tôi cũng có thể chọn nhóm 4 khi mã hóa 13 cấp bậc kể từ 13 4 = 28 , 5612 15 = 32 , 768 . Nó không phải là một sự phù hợp chặt chẽ kể từ 15 / 4 = 3,75 nhưng 26 / 7 = 3,714241313428,56121532,76815/4= =3,7526/7= =3.714. Vì vậy, số bit cho mỗi thẻ là hơi thấp mỗi thẻ nếu chúng ta sử dụng phương pháp đóng gói.26/7

Vì vậy, nhìn vào , chúng tôi chỉ đơn giản là tìm kiếm vị trí thứ tự của các cấp bậc đó trong danh sách " 23456789 T J Q K A " của chúng tôi . Ví dụ: thứ hạng thẻ thực tế đầu tiên là 5 có vị trí tra cứu trong chuỗi tra cứu thứ hạng 4 . Chúng tôi chỉ coi 7 vị trí xếp hạng này là số 13 cơ sở bắt đầu bằng 0 (vì vậy vị trí 4 chúng tôi có trước đây sẽ thực sự là 3). Chuyển đổi trở lại cơ sở 10 (cho mục đích kiểm tra), chúng tôi nhận được 15 , 565 , 975 . Trong 2654Một236J23456789TJQKMột547131015,567,97526bit nhị phân, chúng tôi nhận được .00111011011000010010010111

Bộ giải mã hoạt động theo cách rất giống nhau. (Ví dụ), chuỗi bit đó sẽ chuyển đổi thành số thập phân (cơ số 10) để lấy 15 , 565 , 975 , sau đó chuyển đổi nó thành cơ sở 13 để lấy các giá trị bù vào chuỗi tra cứu xếp hạng, sau đó nó sẽ tái tạo lại thứ hạng cùng một lúc và được bản gốc 54 một 236 J đầu tiên 7 thẻ. Lưu ý rằng kích thước khối của bit sẽ không phải là 26 nhưng sẽ luôn bắt đầu ở mức 26 trong mỗi sàn. Cả bộ mã hóa và giải mã đều có một số thông tin quan trọng về dữ liệu boong ngay cả trước khi chúng hoạt động. Đó là một điều đặc biệt tốt đẹp về thuật toán này.2615,567,9751354Một236J7

Mỗi # ngạch còn lại (ví dụ như có groupsize riêng của mình và chi phí (# bit mỗi thẻ). Chúng được tìm thấy bằng thực nghiệm chỉ chơi xung quanh với sức mạnh của 13 , 12 , 11 ... và sức mạnh của 2 . Tôi đã giải thích làm thế nào tôi có được các nhóm khi chúng ta có thể nhìn thấy 13 cấp bậc, vậy còn khi chúng ta giảm xuống còn 12 cấp bậc thì sao? Phương pháp tương tự. Nhìn vào sức mạnh của 12 và dừng lại khi một trong số chúng đến rất gần với sức mạnh 2 nhưng chỉ hơi ở dưới nó. 13,12,11...,2,1)13,12,11 ...21312122 = 248 , 832 2 18 = 262 , 144 . Đó là một phù hợp khá chặt chẽ. Số bit mã hóa nhóm này là 18 / 5 = 3,6 . Trong 13 nhóm Thứ hạng của nó là 26 / 7 = 3,714 như vậy là bạn có thể thấy, khi số lượng cấp bậc không hàn giảm (cấp bậc được làm đầy lên như 5555 , 3333 ), số lượng các bit để mã hóa các thẻ giảm.125248,832218262,14418/53.61326/73.71455553333

Dưới đây là danh sách đầy đủ các chi phí của tôi (# bit trên mỗi thẻ) cho tất cả các cấp bậc có thể được nhìn thấy:

12 18 / 5 = 3,600 = 3 3 / 5 11 7 / 2 = 3,500 = 3 1 / 2 10 10 / 3 = 3,333 = 3 1 / 3 9 16 / 5 = 3.200 = 3 1 / 5 8 3 / 113    26/7= =3.714= =3  5/7
12    18/5= =3.600= =3  3/5
11      7/2= =3.500= =3  1/2
10    10/3= =3.333= =3  1/3
  9    16/5= =3.200= =3  1/5
7 17 / 6 = 2,833 = 2 5 / 6 6 13 / 5 = 2,600 = 2 3 / 5 5 7 / 3 = 2,333 = 2 1 / 3 4 2 / 1 = 2.000 = 2 3 5 / 3 = 1,667 = 1 2 / 3 2 1 /  số 8      3/1= =3.000= =3
  7    17/6= =2.833= =2  5/6
  6    13/5= =2.600= =2  3/5
  5      7/3= =2.333= =2  1/3
  4      2/1= =2.000= =2
  3      5/3= =1.667= =1  2/3
  2      1/1= =1.000= =1
  1      0/1..4= =0,0= =0

75,6,7,7,7,7,KK1312713K21,2,3 ...3131720

16813,12,11

10777748747S. Nếu bộ bài kết thúc trên một cặp (chẳng hạn như 77), bộ ba / bộ (chẳng hạn như 777) hoặc bộ tứ (chẳng hạn như 7777), chúng tôi sẽ nhận được khoản tiết kiệm bổ sung cho bộ bài đó bằng thuật toán của tôi.

3222613163232

Trong bộ bài đầu tiên trong datafile, việc mã hóa thẻ như sau (sơ đồ sẽ đến sau). Định dạng là (nhóm, bit, chế độ mã hóa xếp hạng):

7,26,1372613
7,26,13
7,26,13
5,18,12
5,18,12
3,10,10
3,  9,  số 8
6,17,  7
5,13,  6
3,  5,  3
1,  0,  1

521683.23

181/33.23.254545454722772277 ...32222333344445555666677778888999999TTTTJJJJQQQQKKKKMộtMộtMộtMột40

1103,7Ksố 8101Thẻ còn lại. Điều này rất quan trọng vì nó làm cho quá trình mã hóa hiệu quả hơn khi bộ giải mã có thể đưa ra các giả định chính xác mà không cần bộ mã hóa phải truyền thêm thông điệp đến nó.

313121110

         26             26             26            18         18       10      9          17           13        5     0
    54A236J  87726Q3  3969AAA  QJK7T  9292Q  36K  J57   T8TKJ4  48Q8T  55K  4
13                                            12                    xy     98         7              6        543     2 1  0

2166175168bit. Lưu ý rằng chúng tôi chỉ có 4 số duy nhất ở cuối bộ bài nhưng nếu thay vào đó chúng tôi có tất cả bốn chiếc 4s ở đó, thì đó là trường hợp tốt hơn và chúng tôi chỉ cần 161 bit để mã hóa bộ bài đó, một trường hợp trong đó việc đóng gói thực sự đánh bại entropy của một mã hóa nhị phân thẳng của vị trí thứ tự của nó.

Bây giờ tôi có mã được triển khai để tính toán các yêu cầu bit và nó đang hiển thị cho tôi trung bình, khoảng 175 bit trên mỗi sàn với mức thấp 155 và mức cao là 183 cho tệp thử nghiệm 3 triệu boong. Vì vậy, thuật toán của tôi dường như sử dụng thêm 9 bit cho mỗi bộ so với mã hóa nhị phân thẳng của phương thức vị trí thứ tự. Không quá tệ khi chỉ cần thêm 5,5% dung lượng lưu trữ. 176 bit chính xác là 22 byte nên tốt hơn một chút so với 52 byte trên mỗi sàn. Boong trường hợp tốt nhất (không hiển thị trong 3 triệu tệp thử nghiệm boong) gói tới 136 bit và boong trường hợp xấu nhất (đã xuất hiện trong testfile 8206 lần), là 183 bit. Phân tích cho thấy trường hợp xấu nhất là khi chúng tôi không nhận được bộ tứ đầu tiên cho đến khi gần (hoặc tại) thẻ 40. Sau đó, khi chế độ mã hóa muốn giảm nhanh, chúng tôi bị "kẹt" các khối điền (lớn bằng 7 thẻ) trong một chế độ mã hóa bit cao hơn. Mọi người có thể nghĩ rằng việc không nhận được bất kỳ quads nào cho đến khi thẻ 40 sẽ khá hiếm khi sử dụng một cỗ bài được xáo trộn tốt, nhưng chương trình của tôi nói với tôi rằng nó đã xảy ra tới 321 lần trong 3 triệu sàn để có khoảng 1 trên 9346 sàn. Đó là thường xuyên hơn mà tôi đã mong đợi. Tôi có thể kiểm tra trường hợp này và xử lý nó với ít bit hơn nhưng hiếm khi nó không ảnh hưởng đến các bit trung bình đủ.

Ngoài ra đây là một cái gì đó rất thú vị. Nếu tôi sắp xếp bộ bài trên dữ liệu bộ bài thô, độ dài của các tiền tố lặp lại một số lần đáng kể chỉ bằng khoảng 6 (chẳng hạn như 222244). Tuy nhiên, với dữ liệu được đóng gói, độ dài đó tăng lên khoảng 16. Điều đó có nghĩa là nếu tôi sắp xếp dữ liệu được đóng gói, tôi sẽ có thể nhận được một khoản tiết kiệm đáng kể bằng cách chỉ ra cho bộ giải mã một tiền tố 16 bit và sau đó chỉ xuất phần còn lại của các sàn (trừ tiền tố lặp lại) có cùng tiền tố đó, sau đó chuyển sang tiền tố tiếp theo và lặp lại. Giả sử tôi tiết kiệm thậm chí chỉ 10 bit trên mỗi sàn theo cách này, tôi nên đánh bại 166 bit trên mỗi sàn. Với kỹ thuật liệt kê được người khác nêu, tôi không chắc liệu tiền tố có dài như thuật toán của tôi không. Ngoài ra tốc độ đóng gói và giải nén bằng thuật toán của tôi là tốt đáng ngạc nhiên.

Về mức độ nén thứ 2 trong đó tôi sắp xếp các bit đầu ra của thuật toán của mình sau đó sử dụng mã hóa "khác biệt": Một phương pháp rất đơn giản là mã hóa 61.278 tiền tố 16 bit duy nhất hiển thị ít nhất hai lần trong dữ liệu đầu ra (và tối đa trong 89 lần được báo cáo) chỉ đơn giản là một bit đầu 0 trong đầu ra để chỉ ra cho bộ giải nén cấp 2 rằng chúng tôi đang mã hóa một tiền tố (chẳng hạn như 0000111100001111) và sau đó bất kỳ sàn đóng gói nào có cùng tiền tố đó sẽ đi theo với 1 bit đầu chỉ ra phần không tiền tố của bộ bài đóng gói. Số sàn trung bình được đóng gói có cùng tiền tố là khoảng 49 cho mỗi tiền tố, không bao gồm số sàn duy nhất (chỉ có 1 sàn có tiền tố cụ thể đó). Dường như tôi có thể tiết kiệm khoảng 15 bit cho mỗi bộ bài bằng cách sử dụng chiến lược đơn giản này (lưu trữ các tiền tố phổ biến một lần).

Sau mức nén thứ 2 bằng cách sử dụng mã hóa chênh lệch (tiền tố) của đầu ra chuỗi bit được sắp xếp của bộ mã hóa đầu tiên, giờ tôi nhận được khoảng 160 bit trên mỗi sàn. Tôi sử dụng tiền tố dài 18 và chỉ lưu nó nguyên vẹn. Vì hầu hết tất cả (245013 trong số 262144 = 93,5%) trong số các tiền tố 18 bit có thể xuất hiện, sẽ tốt hơn nếu mã hóa các tiền tố. Có lẽ tôi có thể sử dụng 2 bit để mã hóa loại dữ liệu nào tôi có. 00 = độ dài thông thường 18 tiền tố được lưu trữ, 01 = "1 tiền tố lên" (giống như tiền tố trước trừ 1 được thêm vào), 11 = mã hóa thẳng từ đóng gói cấp 1 (trung bình khoảng 175 bit). 10 = mở rộng trong tương lai khi tôi nghĩ ra một thứ khác để mã hóa sẽ tiết kiệm bit.

Có ai khác đánh bại 160 bit mỗi sàn chưa? Tôi nghĩ rằng tôi có thể nhận được mức thấp hơn một chút với một số thử nghiệm và sử dụng các mô tả 2 bit tôi đã đề cập ở trên. Có lẽ nó sẽ chạm đáy ở 158ish. Mục tiêu của tôi là đưa nó lên 156 bit (hoặc tốt hơn) bởi vì đó sẽ là 3 bit cho mỗi thẻ hoặc ít hơn. Rất ấn tượng. Rất nhiều thử nghiệm để đưa nó xuống mức đó bởi vì nếu tôi thay đổi mã hóa cấp đầu tiên thì tôi phải kiểm tra lại mã hóa cấp 2 tốt nhất và có nhiều kết hợp để thử. Một số thay đổi tôi thực hiện có thể tốt cho dữ liệu ngẫu nhiên tương tự khác nhưng một số thay đổi có thể bị sai lệch đối với tập dữ liệu này. Không thực sự chắc chắn nhưng nếu tôi bị thôi thúc, tôi có thể thử thêm 3 triệu tập dữ liệu để xem điều gì xảy ra nếu tôi nhận được kết quả tương tự trên đó.

1050

Có ai có bất kỳ ý tưởng nào về cách làm cho thuật toán của tôi tốt hơn như những trường hợp khác tôi nên mã hóa để giảm trung bình bit cho mỗi tầng không? Bất kỳ ai?

Thêm 2 điều nữa: 1) Tôi hơi thất vọng vì nhiều người không ủng hộ giải pháp của tôi, mặc dù không tối ưu về không gian, nhưng vẫn rất tốt và khá dễ thực hiện (Tôi đã làm việc tốt). 2) Tôi đã phân tích trên 3 triệu cơ sở dữ liệu boong của mình và nhận thấy rằng thẻ xảy ra thường xuyên nhất trong đó xếp hạng thứ nhất (chẳng hạn như 4444) là ở thẻ 26. Điều này xảy ra khoảng 6,711% thời gian (cho năm 20122 trong số 3 triệu sàn ). Tôi đã hy vọng sử dụng thông tin này để nén nhiều hơn, chẳng hạn như bắt đầu ở chế độ mã hóa 12 ký hiệu vì chúng ta biết trung bình chúng ta sẽ không thấy mọi thứ hạng cho đến khi về trung gian nhưng phương pháp này không thể nén được vì chi phí vượt quá mức tiết kiệm. Tôi đang tìm kiếm một số điều chỉnh cho thuật toán của tôi mà thực sự có thể tiết kiệm bit.

Vì vậy, có ai có bất kỳ ý tưởng nào tôi nên thử tiếp theo để tiết kiệm một vài bit trên mỗi sàn bằng thuật toán của tôi không? Tôi đang tìm kiếm một mô hình xảy ra đủ thường xuyên để tôi có thể giảm các bit trên mỗi sàn ngay cả khi có thêm chi phí để nói với bộ giải mã mô hình nào sẽ xảy ra. Tôi đã suy nghĩ điều gì đó với xác suất dự kiến ​​của các thẻ chưa nhìn thấy còn lại và bỏ tất cả các thẻ còn lại vào một thùng duy nhất. Điều này sẽ cho phép tôi thả vào chế độ mã hóa thấp hơn nhanh hơn và có thể tiết kiệm một số bit nhưng tôi nghi ngờ điều đó.

Ngoài ra, FYI, tôi đã tạo ra 10 triệu xáo trộn ngẫu nhiên và lưu trữ chúng trong cơ sở dữ liệu để phân tích dễ dàng. Chỉ 488 trong số họ kết thúc trong một hình tứ giác (chẳng hạn như 5555). Nếu tôi chỉ đóng gói những người sử dụng thuật toán của mình, tôi nhận được trung bình 165.71712 bit với mức thấp là 157 bit và mức cao là 173 bit. Chỉ hơi thấp hơn 166 bit bằng phương pháp mã hóa khác. Tôi hơi ngạc nhiên khi thấy trường hợp này không thường xuyên (trung bình cứ khoảng 20.492 lần xáo trộn trung bình).


3
Tôi nhận thấy rằng bạn đã thực hiện khoảng 24 lần chỉnh sửa trong khoảng 9 giờ. Tôi đánh giá cao mong muốn của bạn để cải thiện câu trả lời của bạn. Tuy nhiên, mỗi lần bạn chỉnh sửa câu trả lời, nó sẽ đưa câu này lên đầu trang nhất. Vì lý do đó, chúng tôi không khuyến khích chỉnh sửa quá mức. Nếu bạn muốn thực hiện nhiều chỉnh sửa, có thể chỉnh sửa các chỉnh sửa của bạn không, vì vậy bạn chỉ thực hiện một chỉnh sửa sau mỗi vài giờ? (Ngẫu nhiên, lưu ý rằng việc đưa "EDIT:" và "UPDATE:" trong câu trả lời của bạn thường được phong cách nghèo See. Meta.cs.stackexchange.com/q/657/755. )
DW

4
Đây không phải là nơi để đặt báo cáo tiến độ, cập nhật trạng thái hoặc các mục blog. Chúng tôi muốn các câu trả lời được hình thành đầy đủ, không phải "sắp ra mắt" hay "Tôi có một giải pháp nhưng tôi sẽ không mô tả nó là gì".
DW

3
Nếu ai đó quan tâm anh ta sẽ tìm ra giải pháp cải tiến. Cách tốt nhất là chờ câu trả lời đầy đủ và đăng nó sau đó. Nếu bạn có một số cập nhật một blog sẽ làm. Tôi không khuyến khích điều này, nhưng nếu bạn thực sự phải (tôi không thấy lý do hợp lệ tại sao), bạn có thể viết bình luận bên dưới bài đăng của mình và hợp nhất sau. Tôi cũng khuyến khích bạn xóa tất cả các bình luận lỗi thời và kết hợp chúng vào một câu hỏi liền mạch - thật khó để đọc tất cả. Tôi cố gắng tạo ra thuật toán của riêng mình, khác với bất kỳ trình bày nào, nhưng tôi không hài lòng với kết quả - vì vậy tôi không đăng các phần để được chỉnh sửa - hộp câu trả lời dành cho những người đầy đủ.
Ác

3
@DavidJames, tôi hiểu. Tuy nhiên, điều đó vẫn không thay đổi hướng dẫn của chúng tôi: vui lòng không thực hiện nhiều chỉnh sửa. (Nếu bạn muốn đề xuất cải tiến cho trang web, vui lòng gửi bài đăng trên Meta Science Science của chúng tôi hoặc trên meta.stackexchange.com đề xuất nó. Các nhà phát triển không đọc chủ đề bình luận này.) Nhưng trong lúc này, chúng tôi làm việc với phần mềm chúng tôi có và thực hiện nhiều chỉnh sửa không được khuyến khích vì nó đặt câu hỏi lên hàng đầu. Tại thời điểm này, giới hạn bản thân trong một lần chỉnh sửa mỗi ngày có thể là một hướng dẫn tốt để thực hiện. Hãy sử dụng các trình soạn thảo ngoại tuyến hoặc StackEdit nếu điều đó có ích!
DW

3
Tôi không nêu cao câu trả lời của bạn vì nhiều lý do. 1) nó là không cần thiết dài và FAR quá dài dòng. Bạn có thể giảm đáng kể trình bày của nó. 2) có những câu trả lời tốt hơn được đăng, mà bạn chọn bỏ qua vì những lý do không biết đến tôi. 3) hỏi về việc thiếu upvote thường là "cờ đỏ" đối với tôi. 4) Điều này đã liên tục duy trì ở trang đầu do số lượng chỉnh sửa INSane.
Nicholas Mancuso
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.