簡體   English   中英

在 Java 中使用比字符串內容少的字符打印字符串

[英]Printing a string in Java using less characters than the contents of the string

這是為了下學期即將到來的學校額外學分作業。 我必須在屏幕上打印一個段落,但字符數是代碼必須小於段落中的字符數。 該段如下:

“我保證每一個寫有我名字的程序都由我(和我的合著者,如果有的話)編寫,並且我完全理解這個程序。我提交的每個程序都應完全是我自己的工作,除非另有說明。我理解學術不誠實不僅包括抄襲他人的作品,還包括教唆或協助抄襲。與過去或現在的任何其他提交類似的代碼,無論解釋如何,都不會得到認可。我理解學術不誠實的后果是“ “F' for the class。我保證通過編寫自己的程序來致力於學習Java。我將努力注意細節,編​​寫自己和其他程序員都能理解的程序。”

程序中的總字符數應少於承諾中的總字符數(可打印 655 個,總共 793 個)。

該程序可以不接受任何輸入......沒有文件,下載等。

我最初的想法是,因為從來沒有人能夠做到這一點,所以它一定超出了我們目前在課堂上學到的知識的范圍。 由於它必須更少,您顯然不能只是逐行打印段落,這是每個人在作業的第一部分(常規信用)中所做的。

我已經使用 java.util.zip 研究了字符串壓縮,但我一直遇到不允許輸入的問題。 我暫時擱置的一個想法是:有沒有辦法以壓縮形式對字符串進行編碼,使代碼比段落的未壓縮版本更少字符,並且在將字符串打印到控制台時簡單地解壓縮字符串?

我也涉足過 ASCII 值,但是,ASCII 值僅表示字符,並且所有 ASCII 值的字符長度都比它們用來表示的字符長,所以我沒有看到它的用途。

我現在確定的想法是取最長重復的單詞並為它們分配一個字符串變量名稱。 然后,簡單地用可變連接樣式替換段落中的單詞。 到目前為止,這是我的代碼:

import static java.lang.System.out;

public class Pledge {
  public static void main(String[] args){
    String s=" understand ",p=" program",z=" academic dishonesty ",c=" copying",i="I pledge ";
    out.println(i+"that every"+p+" with my name on it shall be written by me (and my co-authors, if any) and that i fully"+s+"the"+p+". Every"+p+" I submit shall be entirely my own work unless otherwise attributed. I"+s+"that"+z+"not only includes"+c+" other people's work, but also abetting or facilitating"+c+". Code that is similar to any other submission past");
    out.println("or present will get no credit whatever the explanation. I"+s+"that the consequence of"+z+"is a grade of 'F' for the class."+i+"to devote my efforts to learning Java by writing my own"+p+"s. I shall strive to be attentive to detail and write"+p+"s "+s+"able by myself and other"+p+"mers.");
  }
}

附加代碼是 762 個可打印字符。 由於我有 112 個字符,而且代碼已經用兩個巨大的 println 語句看起來很糟糕,我有點覺得我沒有走在正確的軌道上。 我不希望有人為我編寫任何代碼(我討厭那樣),但是將不勝感激將我推向正確方向的一些提示或技巧。 謝謝!

您可能想要研究的一件事是Huffman encoding 該方法類似於您發布的程序中的方法,但在如何壓縮段落方面更加徹底。 所以你可以壓縮文本(預先),將壓縮版本放在你的源文件中,解壓縮並打印。

也有一些小技巧可以減少一些字符; 例如,

  • main(String[] args)可以是main(String[]v) (保存了 4 個字符)
  • 您可以使用比Pledge短的名稱,也可以是單字符名稱(保存 5 個字符)
  • 您可以將所有內容放在一行(保存了許多字符)

它們是小事,但它們會加起來。

一個創造性的解決方案可能是用 Unicode 編寫程序並使用 UTF-16 對字符串進行編碼。 這允許您使用“可打印字符”數量的一半來存儲字符串。 例如:

public static void main(String[] args) throws Exception {
    String s = "䤠灬敤來⁴橈琠敶敲礠灲潧牡洠";
    System.out.println(new String(s.getBytes("UTF-16BE"),"UTF-8"));
}

打印I pledge that every program 輸出是 28 個字符,但用於存儲字符串的“可打印字符”的數量僅為 14。要編碼 793 個可打印字符,字符串需要 397 個字符,剩下 258 個字符用於實際代碼.

您當前方法的改進是使用printf()及其顯式參數索引功能。 這將為原始字符串中的每次出現節省 1 個字符(從而讓您“壓縮”較短的子字符串。它還擺脫了字符串變量聲明,即每個子字符串少三個字符和一點。

劇透的 ideone 版本在這里: http ://ideone.com/lnrTrG – 我設法將它減少到 784 個字符,而不必使用任何非常聰明的東西。 我對提取的子字符串的選擇也可能不是最佳的。

我嘗試使用MessageFormat.format()實現相同的目標,但它不會替換所有占位符。 考慮到printf()版本的限制有多接近,有可能壓縮較短子字符串的能力(因為MessageFormat的顯式索引占位符比printf()的短一個字符)甚至不會抵消額外的 32來自java.text.MessageFormat.format()的開銷字符。 (也就是說,它可能值得一試。您僅在占位符上就保存了 29 個字符,因此很接近。)


您問題中的另一點也有直接答案:

有沒有辦法以壓縮形式對字符串進行編碼,使代碼比段落的未壓縮版本更少字符,並且在我將其打印到控制台時簡單地解壓縮字符串?

您已經找到java.util.zip ,缺少的部分是base-64 encoding 這將允許您將壓縮字節存儲在由可打印字符組成的字符串中。 它將占用比編碼數組長度更多的字符,但(幸運的是)遠少於原始字符串。 (它也應該比直接寫出字節數組值更短。)您可以使用DatatypeConverter的實用方法來處理這種編碼。 (感謝@owlstead 的提示。)

我的同事提出的一種比 base-64 更好的方法是簡單地使用像 Latin-1 這樣的遺留字符集對壓縮數據進行編碼。 由於大多數 Latin-1 字符是可打印的,因此可以使用一個字符將它們寫入 Java 字符串文字中。 需要轉義的少數幾個仍然比 base-64 更不臃腫。 如果您的源文件也可以用 Latin-1 編碼,這也將避免爭論字符和字節之間的區別。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM