高温辐射固化剂


19

背景

在这个站点上,我们偶尔会遇到一些问题,要求对程序进行“辐射加固”。这意味着程序必须能够删除一个或多个字节,无论删除哪个字节。

对于在编程挑战中经常遇到的任务很常见,很自然地想要制作一种特别适合这些挑战的语言。鉴于自然的方法是添加一些元数据,以使反向破坏成为可能,因此,实际上并不是真正需要设计的语言,而是一种编码。这个想法是将每个输入转换为一个字节序列,这样即使对序列稍加照射,也可以提取原始输入。

任务

编写两个程序或函数,E(编码器)和D(解码器),使得:

  • E接受两个参数,一个八位字节序列(在本规范中称为“ 输入 ”)和一个非负整数“ radiation ”,并输出一个八位字节序列“ encoding ”。
  • D接受一个参数,即八位字节序列(“ encdng ”),并输出八位字节序列“ reconstruction ”;
  • 如果同时运行E和D(使用encdng,则D的输入,通过从编码中删除不超过辐射元素(不一定连续)来选择),那么无论删除了哪些字符以形成encdng重构都将等于输入

澄清说明

  • 如果您提交的功能,你不必叫他们ED; 您可以选择最适合您的语言的名称。
  • “八位位组”基本上是0到255之间的整数,您可以将其编码为整数,字符或任何适合您的语言的字符。
  • E和D必须完全是确定性的(即给它们相同的输入将始终产生相同的输出,其中“输入”定义为E的输入辐射,或D的编码)。特别是,E可能不会通过边信道将信息传达给D。
  • 删除是通过删除序列的一个元素来完成的。可以考虑在编辑器中打开序列,将光标置于任意点,然后按Backspace键。如果一个元素出现多次,则可能只删除该元素的一个副本(即,同一八位位组的其他实例将不受影响)。
  • 尽管仅根据相当短的输入量来计算分数,但是您的程序在理论上必须对任何输入量辐射都有效。特别是,无论input中出现哪个八位字节,它都必须起作用。(很抱歉,希望使用他们知道的不可打印字符的能力不会出现在输入中,但是我需要确保输入不可压缩,以便挑战在于辐射硬化而不是压缩。)
  • 您可以提交定义两个功能的一个文件。两个文件,每个文件都定义一个功能或都是完整程序;或三个文件,其中两个分别实现D和E(通过完整程序或通过定义函数),第三个文件是D和E通用的头文件或库。无论使用哪种提交形式,则您的编程语言实现必须能够理解两个程序而无需文件位置等其他参数(否则,按照我们的标准规则,您必须以不寻常的方式调用实现以支付字节罚款)。

胜利条件

对于每个长度辐射,令f长度辐射)为编码 s 的总长度,其对应于具有长度length的所有输入以及给定的辐射。(也就是说,f长度辐射)= 输入总和的长度为长度 length(E(输入辐射))。)然后令g长度辐射)等于f长度辐射)÷256 长度。换句话说,对于给定的输入长度和给定的辐射硬化要求,g是编码输出的平均长度。(理论上,您可以通过蛮力计算出来,但是以这种方式计算出您的分数可能会花费很长的时间。我希望大多数提交者能够对他们的分数做出数学上的论证。不确定,发布一个近似分数,如果另一个条目发布了相似的分数,您或其他人可以更深入地计算它。)

您的分数等于0到9(含)范围内的所有辐射g长度辐射)的总和,0到99(含)范围内的所有长度的总和,加上(主要是避免硬编码,或者如果有人发现了数学上完美的编码;否则,这可能是一个最小的因素)提交给挑战的字节总数(加上对要求异常解释器标志或特定文件名之类的标准惩罚)。获胜者是得分最低的作品(被第一次提交的作品打破)。


解码器也可以知道辐射参数吗?
orlp

(或长度,但我相信,对于大多数方案,知道其中一个应该可以给您另一个)
orlp

1
@orlp:不,它只有字符串。在辐射加固问题中,解码器(即语言)不知道所使用的辐射规则,因此您的解码器也不知道它们。它必须从输入中推断出它们。

根据这段计算机友好的视频,我将制作一种语言,以3字节的三元组形式接受编码:如果它们不完全匹配,则说明出现了问题,并且我们有足够的信息来找出正确的值。可能有一种方法可以用更少的来完成此操作,但目前我还没有头脑去弄清楚该如何做。
Draco18s

您如何结合头文件和程序?
CalculatorFeline

Answers:


8

CJam,得分≤286,516 + 54 + 36 = 286,606

编码器

{_{1\+_:e>)_0a+@@b0\{{)_256b_,\e`,-}g}*256b+\)e*}{*}?}

在线尝试!

解码器

{_{e`1f=(\256b{256b_,\e`,=},,\b1>}&}

在线尝试!

这两个都接受并返回一个列表整数。为了方便起见,TIO链接包括从字符串到字符串的转换。请注意,对于较长的字符串,这些效率极低。如果您想再输入几个字符,建议您使用带有小字符代码的字符。

创建防辐射编码的基本思想包括两个步骤:

  1. 查找一个永远不包含两个连续相同八位字节的编码。
  2. 重复编码字符串中的每个八位位组r +1次,其中r是辐射水平。

这样,辐射就不能完全删除同一字符的一个运行,因此我们可以通过从每个运行中获取一个字符然后解码步骤1来解码字符串。

因此,唯一有趣的部分是找到永远不会产生重复八位位组的编码。基本思想是使用类似A043096的数字系统。也就是说,要对整数N进行编码,我们只需以某个底数b为单位进行计数,跳过具有重复八位位组的所有数字。我相信最多可以用d位数字表示的数字数量与双射基数b-1可以表示的数字数量相同(因为当您要写这样的数字时,可以在每个位置的b-1位数字之间选择,而不违反约束。

当然,要获得最大压缩,我们将使用b = 256。要将输入转换为整数,我们也可以使用基本转换。如果我不懒惰,那么我将使用双射基数作为输入,但是现在我只是在前面加一个1(以确保没有前导零),然后使用最小的基数,以使输入小于基数。

然后将此基数加在编码之前(以便解码器知道要使用哪个基数),并以0八位字节与剩余数分开(这是可行的,因为剩余数永远不会以零开头)。作为次要的优化,空字符串仍然是空字符串。

我之所以没有计算出准确的分数,是因为我只是根据每个输入的长度和最大八位位组计算每个输入将持续多长时间的上限。但是,对于这两个参数,通常会有两种不同的输出长度,而且我还没有弄清楚它们之间发生转折点的位置。我还使用了通常的基数255而不是双射基数255的长度来估计该长度,该长度再次比所需的长度稍大。我用于计算的确切Mathematica代码如下:

num[l_, 1] = 0;
num[l_, base_] := num[l, base] = base^l - Sum[num[l, b], {b, base - 1}]
Sum[
  num[l, b]*(r + 1)*(2 + IntegerLength[2*b^l - 1, 255])/256^l, 
  {r, 0, 9}, {l, 1, 99}, {b, 2, 256}
]
N@%

num[l, b]应该给出l具有最大八位位组的长度的字符串数b-1(除了b == 1,我将其硬编码为,0因为我总是至少使用base 2)。


“假设平均长度为N的字符串不能在辐射级别r的少于(r + 1)* N个八位位组中被编码。” 我认为没有任何理由是真的。看到存在O(N + r)的编码方案,我不会感到惊讶。
orlp

1
@orlp我不知道怎么可能,但是我期待被证明是错误的。:)
Martin Ender

好主意。我不了解CJam,但是从您的描述来看,这听起来像是您将基础放在编码数据的前面。如果是这样,如果从前置数据中删除了字符,是否有问题?(这是我@Leo指出的错误,我必须解决我的问题。)
Mitchell Spector

@MitchellSpector会在重复每个字符r + 1次之前添加基数。因此,底座也是辐射安全的。
Martin Ender

很好-这也是我最终在解决方案中所做的事情。您只需要确保解码器可以在知道基本内容之前就可以解码前置数据。
米切尔·史派克特

6

bash + GNU实用程序,得分294506 283468

编辑1:修复了@Leo注意到的问题-谢谢!

编辑2:改进了辐射参数的编码方法,以获得更好的分数。

编码器(97字节):

for((j=0;j<$1;j++)){ p+=p\;;}
(sed 's/\(.\)\1/\1a\1a/g'<<<$1;cat)|xxd -p -c1|sed ${p-;}|xxd -r -p

解码器(121字节):

read n
n=`sed 's/\(.\)\1*/\1/g'<<<$n`
sed -r "s/( ..)\1{0,${n//a}}/\1/g"<<<' 0a '`xxd -p -c1`|sed 's/^ [^ ]*//'|xxd -r -p

对于编码器:八位位组序列作为字符在stdin中传递,辐射参数r作为参数传递。

对于解码器:在stdin中以字符形式传递的输入。

对于两者:在stdout上输出。

编码器在输入数据前添加r的数字,并在每对连续的相同数字之间插入一个字符“ a”,后跟一个换行符。然后,它将复制所有输入(从前置字符开始),并用该字符的r + 1个副本替换每个字符。

解码器取消此操作,遍历其输入中的每个剩余字符x,在x之后跳过x的r个连续的相同副本,并打印剩余的内容。前置数据没有重复的字符,因此可以在知道r之前对其进行解码。此时,r是已知的,并且需要该值才能正确解码其余数据。

您可以检查此方法是否有效,即使原始输入重复了相同的字符。


分数计算:

假设输入的长度为L,辐射参数为r(在计分计算中最多为9,因此它适合一位数字,因此没有连续的重复字符)。前置数据为2个字节(数字,换行符),因此编码流的输出为(r + 1)(L + 2)个字节。

所以g(L,r)=(r + 1)(L + 2)

因此,总分可以计算为

在此处输入图片说明


如果删除的八位字节是第一个八位字节怎么办?解码器将无法r读取
Leo

@Leo你是对的。我明天要解决这个问题-今晚太晚了。感谢您发现它。
米切尔·史派克特

@Leo我认为可以通过在r的每个数字中包含r + 1个副本,再加上r + 1个换行符来解决此问题。如果是正确的话,分数不会增加太多。
米切尔·史佩克特

这样的事情应该起作用。我认为您应该采取一些其他措施,以确保它在较高的辐射(例如的辐射222)下正常运行,但是幸运的是,分数是根据辐射0-9计算得出的,因此不会受到太大影响。PS我正在考虑实现相同的编码,这就是为什么我立即发现错误的原因;)
Leo

@Leo是,该修补程序适用于对辐射的所有值,即使分数只需要到账户辐射值至多9
米切尔斯佩克特

3

Perl +数学:: {ModInt,多项式,素数:: Util},得分≤92819

$m=Math::Polynomial;sub l{($n,$b,$d)=@_;$n||$d||return;$n%$b,l($n/$b,$b,$d&&$d-1)}sub g{$p=$m->interpolate([grep ref$_[$_],0..$map{$p->evaluate($_)}0..$}sub p{prev_prime(128**$s)}sub e{($_,$r)=@_;length||return'';$s=$r+1;s/^[␀␁]/␁$&/;@l=map{mod($_,p$s)}l(Math::BigInt->from_bytes($_),p$s);$@l+$r>p($s)&&return e($_,$s);$a=0;join'',map{map{chr$_+$a}l($_->residue,128,$s,($a^=128))}g(@l)}sub d{@l=split/([␀-␡]+)/,$_[0];@l||return'';$s=vecmax map length,@l;@l=g map{length==$s&&mod($m->new(map{ord()%128}split//)->evaluate(128),p$s)}@l;$$_=$m->new(map{$_->residue}@l)->evaluate(p$s)->to_bytes;s/^␁//;$_}

控制图片用于表示相应的控制字符(例如,文字NUL字符)。不必担心尝试阅读代码。下面有一个更具可读性的版本。

用运行-Mbigint -MMath::ModInt=mod -MMath::Polynomial -MNtheory=:all-MMath::Bigint=lib,GMP并不是必须的(因此不包含在乐谱中),但是如果您在其他库之前添加它,它将使程序运行更快。

分数计算

此处的算法有些改进,但很难编写(由于Perl没有合适的库)。因此,我在代码中进行了一些大小/效率的权衡,基于可以在编码中保存字节的基础上,试图消除高尔夫方面的每一点是没有意义的。

该程序包含600字节的代码,再加上78字节的命令行选项罚款,从而产生678分的罚款。其余分数是通过在最佳情况和最坏情况(就输出长度而言)字符串上运行程序计算得出的,长度从0到99,每个辐射水平从0到9;平均情况介于两者之间,这为得分设定了界限。(除非另外一个条目得分相似,否则不值得尝试计算出确切的值。)

因此,这意味着来自编码效率的分数在91100到92141之间(含端点),因此最终分数为:

91100 + 600 + 78 = 91778≤分数≤92819 = 92141 + 600 + 78

高尔夫版本,带有注释和测试代码

这是原始程序+换行符,缩进和注释。(实际上,高尔夫版本是通过从该版本中删除换行符/缩进/注释来产生的。)

use 5.010;                    # -M5.010; free
use Math::BigInt lib=>'GMP';  # not necessary, but makes things much faster
use bigint;                   # -Mbigint
use Math::ModInt 'mod';       # -MMath::ModInt=mod
use Math::Polynomial;         # -MMath::Polynomial
use ntheory ':all';           # -Mntheory=:all
use warnings;                 # for testing; clearly not necessary

### Start of program

$m=Math::Polynomial;          # store the module in a variable for golfiness

sub l{ # express a number $n in base $b with at least $d digits, LSdigit first
    # Note: we can't use a builtin for this because the builtins I'm aware of
    # assume that $b fits into an integer, which is not necessarily the case.
    ($n,$b,$d)=@_;
    $n||$d||return;
    $n%$b,l($n/$b,$b,$d&&$d-1)
}

sub g{ # replaces garbled blocks in the input with their actual values
    # The basic idea here is to interpolate a polynomial through all the blocks,
    # of the lowest possible degree. Unknown blocks then get the value that the
    # polynomial evaluates to. (This is a special case of Reed-Solomon coding.)
    # Clearly, if we have at least as many ungarbled blocks as we did original
    # elements, we'll get the same polynomial, thus we can always reconstruct
    # the input.
    # Note (because it's confusing): @_ is the input, $_ is the current element
    # in a loop, but @_ is written as $_ when using the [ or # operator (e.g.
    # $_[0] is the first element of @_.
    # We waste a few bytes of source for efficiency, storing the polynomial
    # in a variable rather than recalculating it each time.
    $p=$m->interpolate([grep ref$_[$_],0..$#_],[grep ref,@_]);
    # Then we just evaluate the polynomial for each element of the input.
    map{$p->evaluate($_)}0..$#_
}

sub p{ # determines maximum value of a block, given (radiation+1)
    # We split the input up into blocks. Each block has a prime number of
    # possibilities, and is stored using the top 7 bits of (radiation+1)
    # consecutive bytes of the output. Work out the largest possible prime that
    # satisfies this property.
    prev_prime(128**$s)
}

sub e{ # encoder; arguments: input (bytestring), radiation (integer)
    ($_,$r)=@_; # Read the arguments into variables, $_ and $r respectively
    length||return''; # special case for empty string
    $s=$r+1; # Also store radiation+1; we use it a lot
    # Ensure that the input doesn't start with NUL, via prepending SOH to it if
    # it starts with NUL or SOH. This means that it can be converted to a number
    # and back, roundtripping correctly.
    s/^[␀␁]/␁$&/; #/# <- unconfuse Stack Exchange's syntax highlighting
    # Convert the input to a bignum, then to digits in base p$s, to split it
    # into blocks.
    @l=map{mod($_,p$s)}l(Math::BigInt->from_bytes($_),p$s);
    # Encoding can reuse code from decoding; we append $r "garbled blocks" to
    # the blocks representing the input, and run the decoder, to figure out what
    # values they should have.
    $#l+=$r;
    # Our degarbling algorithm can only handle at most p$s blocks in total. If
    # that isn't the case, try a higher $r (which will cause a huge increase in
    # $b and a reduction in @l).
    @l+$r>p($s)&&return e($_,$s);
    # Convert each block to a sequence of $s digits in base 128, adding 128 to
    # alternating blocks; this way, deleting up to $r (i.e. less than $s) bytes
    # will preserve the boundaries between each block; then convert that to a
    # string
    $a=0; # we must initialize $a to make this function deterministic
    join'',map{map{chr$_+$a}l($_->residue,128,$s,($a^=128))}g(@l)
}

sub d{ # decoder: arguments; encdng (bytestring)
    # Reconstruct the original blocks by looking at their top bits
    @l=split/([␀-␡]+)/,$_[0];
    @l||return''; # special case for empty string
    # The length of the longest block is the radiation parameter plus 1 (i.e.
    # $s). Use that to reconstruct the value of $s.
    $s=vecmax map length,@l;
    # Convert each block to a number, or to undef if it has the wrong length.
    # Then work out the values for the undefs.
    @l=g map{
        # Convert blocks with the wrong length to undef.
        length==$s&&
            # Convert other blocks to numbers, via removing any +128 and then
            # using Math::Polynomial to convert the digit list to a number.
            mod($m->new(map{ord()%128}split// #/# <- fix syntax highlighting
            )->evaluate(128),p$s)
    }@l;
    # Remove the redundant elements at the end; now that they've reconstructed
    # the garbled elements they have no further use.
    $#l-=$s-1;
    # Convert @l to a single number (reversing the conversion into blocks.)
    $_=$m->new(map{$_->residue}@l)->evaluate(p$s)
        # Convert that number into a string.
        ->to_bytes;
    # Delete a leading SOH.
    s/^␁//;  #/# <- unconfuse Stack Exchange's syntax highlighting
    # Finally, return the string.
    $_
}


### Testing code
use Encode qw/encode decode/;

# Express a string using control pictures + IBM437, to make binary strings
# easier for a human to parse
sub format_string {
    ($_)=@_;
    $_ = decode("Latin-1", $_);
    s/[\0-\x1f]/chr (0x2400 + ord $&)/eag;
    s/\x7f/chr 0x2421/eag;
    s/[ -~\x80-\xff]/decode("IBM437",$&)/eag;
    encode("UTF-8","\x{ff62}$_\x{ff63}")
}

sub test {
    my ($string, $radiation, $samples) = @_;
    say "Input: ", format_string($string);
    my $encoding = e($string, $radiation);
    say "Encoding: ", format_string($encoding);
    say "Input length ", length($string), ", encoding length ", length($encoding), ", radiation $radiation";
    my $decoding = d($encoding);
    $decoding eq $string or die "Mistake in output!";
    say "Decoding: ", format_string($decoding), " from ",
        format_string($encoding);

    # Pseudo-randomly generate $samples radiation-damaged versions.
    srand 1;
    for my $i (1..$samples) {
        my $encdng = $encoding;
        for my $r (1..$radiation) {
            substr $encdng, int(rand(length $encdng)), 1, "";
        }
        my $newdecoding = d($encdng);
        say "Decoding: ", format_string($newdecoding), " from ",
            format_string($encdng);
        $newdecoding eq $string or die "Mistake in output!";
    }

    say "";
    length $encoding;
}

test "abcdefghijklm", 1, 10;
test "abcdefghijklm", 2, 10;
test "abcdefghijklm", 5, 10;
test "abcdefghijklm", 10, 10;
test "\0\0\0\0\0", 1, 10;
test "\5\4\3\2\1", 2, 10;
test "a", 10, 10;

my %minlength = ();
my %maxlength = ();

for my $length (0..99) {
    my ($min, $max) = ("", "");
    $length and ($min, $max) =
        ("\2" . "\0" x ($length - 1), "\1" . "\377" x ($length - 1));
    for my $radiation (0..9) {
        $minlength{"$length-$radiation"} = test $min, $radiation, 1;
        $maxlength{"$length-$radiation"} = test $max, $radiation, 1;
    }
}

say "Minimum score: ", vecsum values %minlength;
say "Maximum score: ", vecsum values %maxlength;

算法

简化问题

基本思想是将这个“删除编码”问题(这不是一个广泛研究的问题)简化为一个擦除编码问题(一个被广泛研究的数学领域)。擦除编码背后的思想是,您正在准备通过“擦除通道”发送数据,该通道有时会用“乱码”字符替换发送的字符,该字符表示错误的已知位置。(换句话说,尽管原始字符仍然未知,但总是很清楚发生腐败的位置。)其背后的想法很简单:我们将输入分成多个长度(辐射)+ 1),并使用每个块中八位中的七位作为数据,而其余位(在此构造中,MSB)在为整个块设置,为整个下一个块清除,为该块设置之间交替之后,等等。因为这些块比辐射参数长,所以每个块中至少有一个字符可以保留到输出中;因此,通过使用相同的MSB提取字符,我们可以算出每个字符属于哪个块。块的数量也总是大于辐射参数,因此在封装中我们总是至少有一个未损坏的块。因此,我们知道所有最长或捆绑时间最长的块均未损坏,从而使我们可以将任何较短的块视为已损坏(因此为乱码)。我们也可以像这样推导辐射参数

擦除编码

至于问题的纠删编码部分,这使用了Reed-Solomon结构的一个简单特殊情况。这是系统的结构:(纠删编码算法的)输出等于输入加上许多额外的块,等于辐射参数。我们可以通过将它们视为乱码,然后通过对它们运行解码算法来“重构”它们的值,从而以一种简单的方式(并且容易理解)计算这些块所需的值。

构造背后的实际思想也非常简单:我们将最小可能程度的多项式拟合到编码中的所有块(从其他元素中插入乱码);如果多项式为f,则第一个块为f(0),第二个块为f(1),依此类推。显然,多项式的次数等于输入块的数量减去1(因为我们首先将多项式拟合到这些多项式,然后使用它来构造额外的“校验”块);并且因为d +1个点唯一地定义了度d的多项式,将任意数量的块(直到辐射参数)加粗,将保留等于原始输入的未损坏块的数量,这足以重建相同的多项式。(然后,我们只需要对多项式求值就可以使一个块乱码。)

基本转换

这里剩下的最后考虑是与块所取的实际值有关。如果我们对整数进行多项式插值,则结果可能是有理数(而不是整数),比输入值大得多,否则是不希望的。因此,我们使用有限域而不是整数。在这个程序中,所使用的有限域是整数模领域p,其中p是最大的素数小于128 辐射 1(即最大的质数,我们可以将等于该质数的许多不同值拟合到块的数据部分中)。有限字段的最大优点是除法(除以0)是唯一定义的,并且将始终在该字段内产生一个值。因此,多项式的内插值将以与输入值相同的方式放入一个块中。

为了将输入转换为一系列块数据,我们需要进行基数转换:将输入从基数256转换为数字,然后转换为基数p(例如,对于辐射参数1,我们有p= 16381)。这主要是由于Perl缺乏基本转换例程而造成的(Math :: Prime :: Util有一些,但它们不适用于bignum基础,并且我们在此处使用的一些素数非常大)。由于我们已经使用Math :: Polynomial进行多项式插值,因此我能够将其重新用作“从数字序列转换”功能(通过将数字视为多项式的系数并对其进行求值),并且该方法适用于bignums正好。但是,相反,我必须自己编写函数。幸运的是,编写起来并不难(或冗长)。不幸的是,这种基本转换意味着输入通常变得不可读。前导零还存在一个问题。

应当注意,输出中不能有p个以上的块(否则两个块的索引将相等,但是可能需要从多项式中产生不同的输出)。仅当输入非常大时才会发生这种情况。这个方案解决了一个非常简单的方法问题:增加辐射(这使得块大和p大得多,这意味着我们可以在更多的数据,并明确导致适合一个正确的结果)。

值得一提的另一点是,我们将空字符串编码为其自身,因为编写的程序否则将在其上崩溃。显然,它也是最佳的编码方式,无论辐射参数是什么,都可以正常工作。

潜在的改进

该程序中主要的渐近效率低下与使用模素数作为所讨论的有限域有关。存在大小为2 n的有限字段(这正是我们在这里想要的,因为块的有效载荷大小自然是128的幂)。不幸的是,它们比简单的模构造要复杂得多,这意味着Math :: ModInt不会削减它(而且我在CPAN上找不到任何库来处理非素数大小的有限字段);我必须用Math :: Polynomial编写一个带有重载算术的整个类才能处理它,到那时,字节开销可能会超过使用(例如16381)而不是(16384)所造成的(很小)损失。

使用2的幂的大小的另一个优点是基本转换将变得更加容易。但是,在任何一种情况下,代表输入长度的更好方法都是有用的。“在模棱两可的情况下添加1”是一种简单但浪费的方法。在这里,双射基数转换是一种可行的方法(想法是您将基数作为数字,而将0作为非数字,因此每个数字都对应一个字符串)。

尽管此编码的渐近性能非常好(例如,对于长度为99的输入和3的辐射参数,该编码始终为128字节长,而不是基于重复的方法将获得的〜400字节),但其性能输入短时效果较差;编码长度始终至少为(辐射参数+ 1)的平方。因此,对于辐射9处非常短的输入(长度1到8),输出的长度仍然是100。(在长度9处,输出的长度有时是100,有时是110。)基于重复的方法显然可以克服这种擦除基于编码的非常小的输入方法;根据输入的大小,可能需要在多种算法之间进行更改。

最后,它并没有真正出现在评分中,但是在辐射参数非常高的情况下,使用每个字节的一点(输出大小的三分之一)来分隔块是浪费的;而是在块之间使用定界符会更便宜。从定界符重构块比使用交替MSB方法要困难得多,但是我相信,至少在数据足够长的情况下才有可能(对于短数据,可能很难从输出中推断出辐射参数)。 。如果目标是渐近理想的方法而不考虑参数,那将是一件值得关注的事情。

(当然,可能有一种完全不同的算法可以产生比该算法更好的结果!)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.