首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >纠错文本

纠错文本
EN

Code Golf用户
提问于 2020-03-08 22:36:57
回答 4查看 3.1K关注 0票数 39

纠正固定文本中的单个字母错误.

输入:下面的段落只有一个错误,其中一个字母a-zA-Z被一个不同的字母a-zA-Z替换。要明确的是,这封信并不是在它出现的任何地方都被替换掉的,而只是在那个地方。例如,第一个单词"In“可能变成"IZ”。空格或标点符号等非字母字符不会受到影响.

输出:段落完全如下,没有打印错误。后面的换行符是可以的。

在信息理论和编码理论中,在计算机科学和通信领域中,差错检测和纠错或差错控制是能够在不可靠的通信信道上可靠地传送数字数据的技术。许多通信信道都受到信道噪声的影响,因此在从源到接收机的传输过程中可能引入错误。错误检测技术允许检测这样的错误,而纠错在许多情况下可以重建原始数据。

带文本的TIO

本文摘自维基百科的文章误差检测与校正。但是,根据标准漏洞,您的代码可能不会从维基百科或其他地方获取文本。

任何站点默认的字符串I/O都是可以接受的。最少字节占上风。如果您能够运行这么多的话,请检查您的解决方案是否适用于所有23001种可能的输入。

EN

回答 4

Code Golf用户

发布于 2020-03-14 04:14:20

Python 3,83字节

代码语言:javascript
运行
复制
def f(s,t=118,u=-10340):
 for x in s:t-=x-96;u-=t
 *l,=s;l[u//t]+=t;return bytes(l)

在网上试试!

我们计算一个自定义的数字校验和,让我们定位并修正错误。这意味着,在我们找到可行的更改之前,不需要尝试可能的更改。因此,代码运行得非常快,允许我们在链接的TIO中在2秒内测试所有23,001个可能的输入。

输入和输出都是字节字符串,这需要Python 3。

校验和

使用下面的代码更容易理解这个想法。

代码语言:javascript
运行
复制
def f(s):
 t=50998-sum(s)
 k=13447420-sum(i*x for i,x in enumerate(s))
 i=k//t
 l=list(s)
 l[i]+=t
 return bytes(l)

在网上试试!

核心是校验和,它提供两个值。正确的字符串(而且只有它)给出了值(50998, 13447420),这些值在上面的代码中使用。

代码语言:javascript
运行
复制
def checksum(s):
 t=sum(s)
 u=sum(i*x for i,x in enumerate(s))
 return(t,u)

在网上试试!

校验和不仅让我们知道字符串是否正确,而且校验和与实际字符串的区别使我们可以推断错误是什么并修复它。这并不取决于字体是否带有字母。

它是如何工作的?

校验和由两个部分组成,每个部分都是一个数字。

t=sum(s)部分只是字符串中(ASCII)值的之和。给定一个字符串,从原来的一个错误,我们可以计算出原始字符和键入字符之间的数字差异,通过比较和原来的和50998。例如,如果我们发现一个51001的和,我们知道错误增加了一个字符3,如a->dM->P

所以,我们知道角色的数量,但不知道是哪一个。也就是说,我们不知道指数。为此,我们使用校验和的第二个值u中给出的附加信息,

代码语言:javascript
运行
复制
u=sum(i*x for i,x in enumerate(s))

在这里,我们把所有的字符加起来,但是每个字符都被赋予一个与其指数相等的乘数,所以零乘以初始字符加上一个乘以下一个,最多是最后一个的529倍。

这个想法类似于一个经典的谜题:

你有10袋硬币。每个袋子都有10枚金币,每个金币重10克,除了一个袋子里装满了重9克但看起来正常的打火机。你有一个数字天平,显示精确的数字权重。你怎样才能确定哪个袋子有假货,只需一个称重?

解决的办法是把袋子的编号从1到10,把1枚硬币从第1袋里放出来,从第2袋里放2枚硬币,从10袋里放到10枚。总共有55枚硬币,所以如果所有硬币都是真的,它们的重量是550克。但是,每个假币的总重量降低了1克。因此,由于假袋将贡献它的指数-重量不足的硬币数,这是多少克以下的550,我们看到。这说明哪个包是假的。(我们也可以使用0-9索引,使用45枚硬币。)

校验和u就是这样工作的。假设错误是索引j,并且由第一个校验和值t确定的d值表示。然后,指数j将导致u中的误差,其乘数等于j,因此它将由j*d关闭。了解dj*d可以让我们通过除法找到键入的索引j

修复错误

错误被固定为*l,=s;l[u//t]+=t;return bytes(l)。这会将字符串转换为列表,用+=修改索引值,然后再将字节串转换回来。这太丑了。注意,字符串和字节字符串在Python中是不可变的,与列表不同,所以我们不能直接修改字符串。

我仍然不清楚默认的字符串I/O允许什么,尽管它已经在挑战中取得了进展。如果我们可以对ASCII值列表进行输入和输出,那么我们可以节省大量代码,特别是通过修改相应的输入列表。

61个字节

代码语言:javascript
运行
复制
def f(l,t=118,u=-10340):
 for x in l:t-=x-96;u-=t
 l[u//t]+=t

在网上试试!

Optimizations

代码语言:javascript
运行
复制
def f(s,t=118,u=-10340):
 for x in s:t-=x-96;u-=t
 *l,=s;l[u//t]+=t;return bytes(l)

我们在上面的代码中保存了一些字符,并进行了一些优化。

与计算校验和值(t,u)和减去目标值不同,我们直接将tu初始化为目标值,迭代地减去对每个字符的贡献。传入原始字符串将使它们都以零结尾,从而在代码中产生除以零的错误。

我们不使用enumerate计算加权和u,而是反复减去运行的和t,从而连续地减去每个字符的值。这有效地计算了反向字符串的加权和,也就是前面最大的权重。但是我们最终得到了一个负的指数,从后面,所以它是可行的。

最后,我们能够获得较短的写校验和值(t,u) = (118,-10340)而不是(50998, 13447420),方法是使用一个稍微不同的校验和,它首先从每个ASCII值中减去96。这是文本的四舍五入的ASCII值,因此减去它,字符串值的平均值大约为零。这使得校验和有正和和负和,使它们接近于零。(118,-10340)的这些值接近1位数,而其中一个值为负值,但我没有找到缩短它们的方法。

我最初计划做所有的校验和计算,模块化一些素数,以使结果的值更短,但无论如何,它们足够短,以至于根本不值得,即使没有上面的优化。

票数 6
EN

Code Golf用户

发布于 2020-03-09 08:09:19

Dyalog Unicode,94字节

代码语言:javascript
运行
复制
g←252|1⊥⊢⍪⎕AV⍳⊣
252|⊢+0,⍨∘(,'⊂⍷≠Eæ×(í/7Ãs·¨\=Ш⍎ëáØ@'∘g∘.⌊⍨'#⌿O⍒`=~{└⊤Üã/cëÖ¶⌹⌹bð'g⍉)23 23⍴-

在网上试试!

使用Unicode编码点的向量作为I/O格式。否则,从字符串转换到字符串需要花费11个字节:

Dyalog Unicode,105个字节

代码语言:javascript
运行
复制
g←252|1⊥⊢⍪⎕AV⍳⊣
⎕UCS 252|46,⍨∘(,-+'⊂⍷≠Eæ×(í/7Ãs·¨\=Ш⍎ëáØ@'∘g∘.⌊⍨'#⌿O⍒`=~{└⊤Üã/cëÖ¶⌹⌹bð'g⍉)23 23⍴-∘⎕UCS

在网上试试!

使用行/col校验和方法,如米切尔·斯派克特的C回答中所示。因为按位XOR不是APL中内置的函数,所以我不得不使用普通和。

是如何工作的

代码语言:javascript
运行
复制
g←252|1⊥⊢⍪⎕AV⍳⊣  ⍝ Auxiliary function: checksums g matrix → checksum vector
          ⎕AV⍳⊣  ⍝ Convert string written in APL SBCS to integer
        ⊢⍪       ⍝ Append the checksum vector at the bottom of the matrix
      1⊥         ⍝ Column-wise sum
  252|           ⍝ Modulo 252

⍝ Main function: Correct the typo based on checksum
252|⊢+0,⍨∘(,'⊂⍷≠Eæ×(í/7Ãs·¨\=Ш⍎ëáØ@'∘g∘.⌊⍨'#⌿O⍒`=~{└⊤Üã/cëÖ¶⌹⌹bð'g⍉)23 23⍴-
23 23⍴-  ⍝ Negate each element and reshape into 23x23 matrix, discarding the last '.'
(...)    ⍝ Pass to the inner tacit function...
'...'g⍉    ⍝ Check rows against the row checksums
∘.⌊⍨       ⍝ Outer product by minimum (rows and columns reversed) with...
'...'∘g    ⍝ Check columns against the column checksums
           ⍝ Result = all-zero matrix except at the typo (difference mod 252)
,          ⍝ Flatten the result
0,⍨∘     ⍝ Append a zero to account for the last '.'
252|⊢+   ⍝ Fix the typo using the offset
票数 2
EN

Code Golf用户

发布于 2020-03-15 19:52:12

C (gcc),125个字节

注意:我的代码在字符串文本中包含两个不可打印的字符\x0c\0x01,它们在代码段中是不可见的。

代码语言:javascript
运行
复制
b,i,j,m,n;C(char*T){b=i=n=0;for(;i<10;b|=("N<Syr4Zd"[i]!=m)<<i++)for(m=j=0;T[j];n^=!i*T[j++])m^=(1&j>>i)*T[j];T[b]^=120^n;}

在网上试试!

文本中的i第四字符是原始文本中所有字符在i第四位为1的位置上的异或。程序对修改后的文本执行相同的XOR。当修改后的字符处于i_th位1的位置时,计算值将有所不同。这给了我们所有修改字符的位置。

最后,我们修改字符,使所有字符的XOR都是原始文本(120)的异或。

票数 2
EN
页面原文内容由Code Golf提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codegolf.stackexchange.com/questions/200761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档