关于unicode:Twitter文本压缩挑战

Twitter text compression challenge

规则

  • 您的程序必须有两种模式:编码和解码。
  • 编码时:

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

    • U+0000U+10FFFF范围内140个码位

      不包括非字符:

      • U+FFFE
      • U+FFFF
      • U+nFFFEU+nFFFF,其中n110十六进制
      • U+FDD0U+FDEF
      • U+D800U+DFFF(代理代码点)。
  • 它可以以您选择的任何合理编码输出;GNU iconv支持的任何编码都被认为是合理的,您的平台本机编码或区域设置编码可能是一个不错的选择。

  • 解码时:

  • 程序应该将编码模式的输出作为输入。
  • 文本输出应该是输入文本的近似值。
    • 离原文越近越好。
    • 不需要任何标点符号。
  • 输出文本应该可以被人阅读,也可以是英语。

    • 可以是L337或LOL。
  • 解码过程可能无法访问编码过程的任何其他输出。除上述规定的输出外;也就是说,不能将文本上载到某个地方并输出URL为解码过程下载,或任何愚蠢的事情。
  • 为了用户界面的一致性,程序的行为必须如下:
  • 您的程序必须是一个脚本,可以使用适当的解释器在平台上设置为可执行,或者可以编译成可执行文件的程序。
  • 您的程序必须以encodedecode作为第一个参数来设置模式。
  • 您的程序必须至少以以下方式之一接受输入:
    • 从标准输入中获取输入,在标准输出中生成输出。
      • my-program encode output.utf
      • my-program decode output.txt
    • 从第二个参数中名为的文件中获取输入,并在第三个参数中名为的文件中生成输出。
      • my-program encode input.txt output.utf
      • my-program decode output.utf output.txt
  • 对于您的解决方案,请发布:
  • 您的完整代码和/或托管在其他地方的指向它的链接(如果它很长,或者需要编译许多文件,或者什么的话)。
  • 如果从代码中看不出它是如何工作的解释或者如果代码很长,人们会对摘要感兴趣。
  • 示例文本,包括原始文本、压缩到的文本以及解码后的文本。
  • 如果你是建立在别人的想法之上,请将它们归为属性。试着对别人的想法进行提炼是可以的,但你必须把它们归为属性。
  • 这些规则是Twitter图像编码挑战规则的变体。


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

    • 任何在一定长度下的任意拉丁1字符串都可以简单地编码(甚至不压缩),而不会丢失到140个字符。简单的估计是280个字符,尽管在竞赛规则中有代码点限制,但它可能比这短一点。
    • 比上述长度稍长的字符串(允许GuestiMate在280到500个字符之间)最有可能使用标准压缩技术收缩为足够短的字符串,以便进行上述编码。

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

  • 将127以上的所有拉丁1字符(主要是重音字母和时髦符号)替换为非重音字母字符中最接近的等效字符,或者可能替换为类似""的通用符号。
  • 将所有大写字母替换为等效的小写形式
  • 用空格替换所有非字母数字(任何剩余符号或标点符号)
  • 用0替换所有数字
  • 好吧,现在我们已经消除了尽可能多的多余字符。现在我们要做一些更大幅度的削减:

  • 用单个字母(balon)替换所有双字母(气球)。看起来很奇怪,但仍希望能被读者理解。
  • 用较短的等价物替换其他常用字母组合(ck表示k,wr表示r等)
  • 好吧,这就是我们所能做到的,让文本可读。除此之外,让我们看看我们是否可以想出一个方法,使文本与原始文本相似,即使它最终不可分解(同样,从字符串末尾开始,每次执行一个字符,当它足够短时停止):

  • 将所有元音(aeiouy)替换为
  • 用l替换所有"高"字母(bdfhklt)
  • 将所有"短"字母(cmnrsvwxz)替换为n
  • 将所有"挂起"字母(gjpq)替换为p
  • 这将给我们留下一个由5个可能值(A、L、N、P和空格)组成的字符串,这将允许我们对相当长的字符串进行编码。

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

    我能想到的唯一其他技术是对普通单词或字母组进行基于字典的编码。这可能对正确的句子有一些好处,但对任意的字符串可能没有好处。


    这是我实际英语的变体。

    每个代码点都有类似于110万个可能的状态。嗯,那有很大的空间。

    所以,我们将所有原始文本都作为词干,并从中获取WordNet合成集。数字被转换成英文名称("四二")。1,1M状态允许我们保存synset id(可以在0到82114之间)、synset内的位置(我想大概有10个变体)和synset type(四个名词、动词、形容词、副词之一)。我们甚至可以有足够的空间来存储单词的原始形式(比如动词时态id)。

    解码器只将synset提供给wordnet并检索相应的单词。

    源文本:

    1
    2
    3
    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.

    变成:

    1
    2
    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

    (在线WordNet测试)。这个"代码"应该取27个代码点。当然,所有"胡言乱语"如"lol"和"l33t"都将永远消失。


    下面是一个简单的例子,它获取一个输入文件并删除所有非文字字符。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    #! 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
    1
    2
    echo Hello, this is, some text | perl sample.pl -e
    Hello this is some text


    paq8o10t<