繁体   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