Java 编程问题-传真压缩
我准备参加一个计算机科学竞赛,完成过去竞赛中的问题。大多数都很简单,但这一个让我很烦…看起来很简单,但我就是做不到 如果您有一个由1和0组成的字符串:Java 编程问题-传真压缩,java,algorithm,binary,compression,fax,Java,Algorithm,Binary,Compression,Fax,我准备参加一个计算机科学竞赛,完成过去竞赛中的问题。大多数都很简单,但这一个让我很烦…看起来很简单,但我就是做不到 如果您有一个由1和0组成的字符串: 100111010001111100101010 将其作为输入然后输出的代码是什么: 1:1 2:0 3:1 1:0 1:1 3:0 5:1 2:0 1:1 1:0 1:1 1:0 其中,每个冒号左边的数字是冒号出现后的数字的次数 那么,另一个例子…输入: 1100011 将输出: 2:1 3:0 2:1 根据问题,这类似于用于压缩传真传
100111010001111100101010
将其作为输入然后输出的代码是什么:
1:1 2:0 3:1 1:0 1:1 3:0 5:1 2:0 1:1 1:0 1:1 1:0
其中,每个冒号左边的数字是冒号出现后的数字的次数
那么,另一个例子…输入:
1100011
将输出:
2:1 3:0 2:1
根据问题,这类似于用于压缩传真传输的算法
用java来回答是最好的,但我真正想要的是伪代码,甚至是关于如何做的想法
提前谢谢。正如我所想的:你为什么要为右边的数字而烦恼呢?它总是在1和0之间交替,不是吗,所以只要假设它从1开始,如果实际序列从0开始,则编码一个初始的0。换句话说,你最终会得到: 123111352111 但基本上你需要跟踪“我现在在看什么?”和“我见过多少?”?如果它改变了,写下你一直在看的内容和计数,然后将“我正在看的内容”更新为新值,计数为1,然后继续。不要忘了在数据末尾写出最后一个值
(我没有给出伪代码或Java,因为我想你会从一些小提示中学到比使用工作代码更多的东西。如果你需要更多提示,就说吧。)这被称为游程编码(RLE),在许多事情中使用(如Windows位图文件格式)来提供非常基本的压缩(尤其是当原始文件包含大量重复值(如位图或传真)且包含相同颜色的长时间运行时)
int[]数组={……..};//您的值。。。
for(int i=0;i
我真正想要的是伪代码,甚至是关于如何做到这一点的想法
以下是一些想法:
- 如何测试字节中的位是1还是0:使用“按位AND”操作屏蔽其他位
- 如何测试字节中的不同位是1还是0:
- 或者,使用不同的位掩码
- 或者,在屏蔽字节之前移位或旋转字节中的位
main()
{
Encoder encoder = new Encoder;
foreach (byte b in inputStream)
{
encoder.input(b);
}
//tell the encoder that the stream is finished
//that there will be no subsequent bytes
///and that the final bits should be flushed now
encoder.finished();
}
class Encoder
{
//member data
bool m_b; //value of the most-recently-processed bit
int m_n; //number of the most-recently-processed bits
//public methods
void finished()
{
//TODO format and write the {m_n}:{m_b} value to output
//and reset m_n to zero
}
void input(byte b)
{
for int (i = 0; i < 8; ++i)
{
//get the bit value
bool bit = getbit(b, i);
//see whether we can append it
bool canAppend =
(bit == m_b) || //new bit is same as previous bit
(0 == m_n); //no previous bit
//flush previous bits if can't append
if (!canAppend)
finished();
//append current bit
m_b = bit;
++m_n;
}
}
//private helper method
bool getbit(byte b, int i)
{
//TODO return the bit value using a mask
}
}
main()
{
编码器=新的编码器;
foreach(inputStream中的字节b)
{
编码器输入(b);
}
//告诉编码器流已完成
//没有后续字节
///现在应该刷新最后的位
编码器。完成();
}
类编码器
{
//成员数据
bool m_b;//最近处理的位的值
int m_n;//最近处理的位数
//公共方法
作废已完成()
{
//TODO格式化并将{m_n}:{m_b}值写入输出
//并将m_n重置为零
}
无效输入(字节b)
{
对于int(i=0;i<8;++i)
{
//获取位值
bool位=getbit(b,i);
//看看我们是否可以附加它
布尔卡纳彭德=
(位==m_b)| |//新位与前一位相同
(0==m_n);//没有前一位
//如果无法追加,则刷新以前的位
如果(!canAppend)
完成的();
//附加当前位
m_b=位;
++穆恩;
}
}
//私人助手法
bool getbit(字节b,int i)
{
//TODO使用掩码返回位值
}
}
编写代码时,不要忘了使用各种输入数据对其进行测试,包括特殊情况(例如,包括一个字节中具有相同值的所有位).我不会嵌套循环-我觉得这相对比较难读。只有一个知道最后看到的值和当前计数的循环更简单。只需使用“如果”来测试更改并输出(如果是)。(这也让你更容易处理IEnumerable。)谢谢你,雷。这正是我想要的。:)谢谢你的帖子,乔恩。我使用了你的提示,比以前做得更深入了,但在查看Ray的代码后,我仍然有一些bug被清除了D
main()
{
Encoder encoder = new Encoder;
foreach (byte b in inputStream)
{
encoder.input(b);
}
//tell the encoder that the stream is finished
//that there will be no subsequent bytes
///and that the final bits should be flushed now
encoder.finished();
}
class Encoder
{
//member data
bool m_b; //value of the most-recently-processed bit
int m_n; //number of the most-recently-processed bits
//public methods
void finished()
{
//TODO format and write the {m_n}:{m_b} value to output
//and reset m_n to zero
}
void input(byte b)
{
for int (i = 0; i < 8; ++i)
{
//get the bit value
bool bit = getbit(b, i);
//see whether we can append it
bool canAppend =
(bit == m_b) || //new bit is same as previous bit
(0 == m_n); //no previous bit
//flush previous bits if can't append
if (!canAppend)
finished();
//append current bit
m_b = bit;
++m_n;
}
}
//private helper method
bool getbit(byte b, int i)
{
//TODO return the bit value using a mask
}
}