Twitter文本压缩挑战

时间:2009-06-18 18:05:41

标签: unicode twitter compression code-golf

规则

  1. 您的计划必须有两种模式:编码解码
  2. 编码时:

    1. 您的程序必须将一些人类可读的Latin1文本作为输入,大概是英文。
      • 忽略标点符号无关紧要。
      • 您只需要担心实际的英语单词,而不是L337。
      • 任何带重音的字母都可以转换为简单的ASCII。
      • 您可以选择如何处理数字。
      • 123
        • 一二三
        • 一百二十三
        • 123
        • 1 2 3
      • 一百二十三
        • 一二三
        • 一百二十三
        • 123
        • 1 2 3
    2. 您的程序必须输出一条可以用

      表示的消息
      • U+0000 - U+10FFFF

        范围内的140个代码点

        排除非字符:

        • U+FFFE
        • U+FFFF
        • U+ n FFFEU+ n FFFF其中< em> n1 - 10十六进制
        • U+FDD0 - U+FDEF
        • U+D800 - U+DFFF(代理代码点)。
    3. 可以以您选择的任何合理编码输出; GNU iconv支持的任何编码都将被视为合理, 并且您的平台本机编码或语言环境编码可能是一个不错的选择。

    4. 解码时

      1. 您的程序应将编码模式的输出作为输入。
      2. 文本输出应该是输入文本的近似值。
        • 越接近原始文本越好。
        • 不需要任何标点符号。
      3. 输出文本应该是人类可读的,也可能是英文。

        • 可以是L337,或lol。
      4. 解码过程可能无法访问编码过程的任何其他输出 除上述指定的输出外; 也就是说,您无法在某处上传文本并输出URL 用于下载的解码过程,或类似的任何东西。
    5. 为了用户界面的一致性,您的程序必须按如下方式运行:
      1. 您的程序必须是可以在具有相应解释器的平台上设置为可执行的脚本, 或者可以编译成可执行文件的程序。
      2. 您的程序必须将encodedecode作为其第一个参数来设置模式。
      3. 您的程序必须至少通过以下方式之一进行输入:
        • 从标准输入获取输入并在标准输出上产生输出。
          • my-program encode <input.txt >output.utf
          • my-program decode <output.utf >output.txt
        • 从第二个参数中指定的文件中获取输入,并在第三个参数中指定的文件中生成输出。
          • my-program encode input.txt output.utf
          • my-program decode output.utf output.txt
    6. 您的解决方案,请发布:
      1. 您的代码,完整的和/或其他地方托管的链接 (如果它很长,或者需要编译许多文件,或者其他东西)。
      2. 解释它是如何工作的,如果代码中没有立即显而易见的话 或者如果代码很长,人们会对摘要感兴趣。
      3. 示例文本,包含原始文本,压缩到的文本以及解码文本。
      4. 如果您的想法是基于其他人的想法,请将其归因于此。 尝试对其他人的想法进行改进是可以的,但必须对它们进行归属。
    7. 规则是Twitter image encoding challenge规则的变体。

4 个答案:

答案 0 :(得分:3)

不确定我是否有时间/精力来跟进实际代码,但这是我的想法:

  • 任意长度的任意LATIN 1字符串都可以简单地编码(甚至不是压缩),不会丢失到140个字符。天真估计是280个字符,虽然比赛规则中的代码点限制,它可能比这短一点。
  • 比上述长度稍长的字符串(允许280到500个字符之间的字符串)很可能使用标准压缩技术缩小为足够短的字符串以允许上述编码。

比这更长的时间,我们开始丢失文本中的信息。因此,执行以下步骤的最小数量,将字符串减少到可以使用上述方法压缩/编码的长度。另外,如果只是在子串上执行这些替换,就不要在整个字符串上执行这些替换。这会使它足够短(我可能会向后遍历字符串)。< / p>

  1. 将127以上的所有LATIN 1字符(主要是重音字母和时髦符号)替换为非重音字母字符中最接近的等效字符,或者替换为“#”等通用符号替换
  2. 将所有大写字母替换为等效的小写字母
  3. 用空格替换所有非字母数字(任何剩余的符号或标点符号)
  4. 将所有数字替换为0
  5. 好的,现在我们已经消除了尽可能多的多余字符,因为我们可以合理地摆脱它们。现在我们要做一些更大幅度的缩减:

    1. 用一个字母(balon)替换所有双字母(气球)。看起来很奇怪,但仍然希望读者能够辨认出来。
    2. 用较短的等值替换其他常用字母组合(CK表示K,WR表示R等)
    3. 好的,这就是我们可以去的地方,并且文字是可读的。除此之外,让我们看看我们是否可以提出一种方法,使文本类似原文,即使它最终不是 deciperable (再次,执行这个从字符串末尾开始的一次字符,当它足够短时停止):

      1. 替换所有元音(aeiouy)
      2. 用l
      3. 替换所有“高”字母(bdfhklt)
      4. 用n
      5. 替换所有“短”字母(cmnrsvwxz)
      6. 用p
      7. 替换所有“悬挂”字母(gjpq)

        这应该给我们留下一个由5个可能的值(a,l,n,p和space)组成的字符串,这应该允许我们编码相当冗长的字符串。

        除此之外,我们只需要截断。

        我能想到的其他技术只能是基于字典的编码,常见的单词或字母组。这可能会为正确的句子带来一些好处,但可能不适用于任意字符串。

答案 1 :(得分:1)

这是我实际英语的变体。

每个代码点都有1100000个可能的状态。嗯,这是一个很大的空间。

因此,我们阻止所有原始文本并从中获取Wordnet同义词。数字被投入英文名称(“四十二”)。 1,1M状态将允许我们保持synset id(可以在0到82114之间),synset内部的位置(我认为~10个变体)和synset类型(四个中的一个 - 名词,动词,形容词,副词) 。我们甚至可能有足够的空间来存储原始形式的单词(如动词时态id)。

解码器只会将同义词输入Wordnet并检索相应的单词。

来源文字:

A white dwarf is a small star composed mostly of electron-degenerate matter. Because a
white dwarf's mass is comparable to that of the Sun and its volume is comparable to that 
of the Earth, it is very dense.

变为:

A white dwarf be small star composed mostly electron degenerate matter because white
dwarf mass be comparable sun IT volume be comparable earth IT be very dense

(用Online Wordnet测试)。这个“代码”应该占用27个代码点。 当然,像“lol”和“L33T”这样的所有“胡言乱语”将永远消失。

答案 2 :(得分:0)

PAQ8O10T&lt;&lt; FTW

答案 3 :(得分:0)

这是一个简单的示例,它接受输入文件并删除任何非单词字符。

#! perl
use strict;
use warnings;
use 5.010;


use Getopt::Long;
use Pod::Usage;
use autodie;

my %opts = (
  infile  => '-',
  outfile => '-',
);
GetOptions (
  'encode|e'    => \$opts{encode},
  'decode|d'    => \$opts{decode},
  'infile|i=s'  => \$opts{infile},
  'outfile|o=s' => \$opts{outfile},
  'help|h'      => \&help,
  'man|m'       => \&man,
);

unless(
  # exactly one of these should be set
  $opts{encode} xor $opts{decode}
){
  help();
}


{
  my $infile;
  if( $opts{infile} ~~ ['-', '&0'] ){
    $infile = *STDIN{IO};
  }else{
    open $infile, '<', $opts{infile};
  }

  my $outfile;
  if( $opts{outfile} ~~ ['-', '&1'] ){
    $outfile = *STDOUT{IO};
  }elsif( $opts{outfile} ~~ '&2' ){
    $outfile = *STDERR{IO};
  }else{
    open $outfile, '>', $opts{outfile};
  }

  if( $opts{decode} ){
    while( my $line = <$infile> ){
      chomp $line;

      say {$outfile} $line;
    }
  }elsif( $opts{encode} ){
    while( my $line = <$infile> ){
      chomp $line;

      $line =~ s/[\W_]+/ /g;

      say {$outfile} $line;
    }
  }else{
    die 'How did I get here?';
  }
}

sub help{
  pod2usage();
}
sub man{
  pod2usage(1);
}
__END__

=head1 NAME

sample.pl - Using GetOpt::Long and Pod::Usage

=head1 SYNOPSIS

sample.pl [options] [file ...]

 Options:
   --help     -h      brief help message
   --man      -m      full documentation
   --encode   -e      encode text
   --decode   -d      decode text
   --infile   -i      input  filename
   --outfile  -o      output filename

=head1 OPTIONS

=over 8

=item B<--help>

Print a brief help message and exits.

=item B<--man>

Prints the manual page and exits.

=item B<--encode>

Removes any character other than /\w/.

=item B<--decode>

Just reads from one file, and writes to the other.

=item B<--infile>

Input filename. If this is '-' or '&0', then read from STDIN instead.
If you use '&0', you must pass it in with quotes.

=item B<--outfile>

Output filename. If this is '-' or '&1', then write to STDOUT instead.
If this is '&2', then write to STDERR instead.
If you use '&1' or '&2', you must pass it in with quotes.

=back

=head1 DESCRIPTION

B<This program> will read the given input file(s) and do something
useful with the contents thereof.

=cut
echo Hello, this is, some text | perl sample.pl -e
Hello this is some text