帮助:外星人程序员只能说ASCII


22

设置场景:

这是一个平均的下午,在忙碌了一天之后,您会通过参加自己喜欢的消遣来放松:回答有关PPCG的许多令人着迷的问题。今天对您而言不是好日子;那些该死的Pyth程序员不断获得最佳答案,这正在杀死您的氛围。突然,您发现一个新问题已发布!你下定决心;这次不是CJammers。奇怪的是,您开始打字,产生了一系列字符。最终产品将成为辉煌的BrainFuck循环的胎儿。您键入并键入。快点!还快!您太专心了,甚至没有注意到屏幕上的灯光开始闪烁。突然,显示器发出绿色光,桌面上印有外星人般的符号。使用无可挑剔的技能,您cat ~/Desktop/aliensymbol并得到一堆数字,一条消息!作为您精明的PPCG程序员,您会注意到它看起来像ASCII。无论您是什么,您都可以print(chr(i) for i in file)解密消息。您首先想到的是:“我需要与社区分享!”。

...

谁会想到的?最早接触外星人的人将是PPCG谦虚的程序员。为什么是我们?也许是因为我们是人类智慧的缩影。也许是因为BrainFuck与我们使用外语差不多。尽管如此,外星人-他们是超智能的生活形式-想要测试他们是否应该将人类归类为聪明人。为了检验我们的智力,外星人要求我们向他们发送一些计算机程序,以证明我们在技术上得到了培养。问题是,他们唯一能理解的人类语言是数字ASCII!

帮助人类向那些生物展示真正的智力阿尔法。我们需要向他们发送一个脚本,该脚本会将基于文本的源代码转换为数字ASCII版本。不幸的是,由于我们的技术不发达(感谢奥巴马),我们必须发送尽可能小的翻译程序。他们选择联系PPCG的好事!

挑战:

挑战的前提很简单:您将编写一个程序,该程序将使用任何程序的源代码(或与此相关的任何常规文本文件),并在每行下方输出带有ASCII转换的空格分隔版本。也就是说,给定一个文本文件的输入,您需要输出该文件的每一行,然后输出一行,该行包含其上方一行中每个字符的ASCII表示(每个数字与其所表示的字符对齐)。

一个例子将大大阐明这一点。以臭名昭著的源代码hello world作为输入:

#include <stdio.h>

int main() {
    printf("hello, world\n");
    return 0;
}

您的程序应输出:

#   i   n   c   l   u   d   e       <   s   t   d   i   o   .   h   >
35  105 110 99  108 117 100 101 32  60  115 116 100 105 111 46  104 62  10

10
i   n   t       m   a   i   n   (   )       {
105 110 116 32  109 97  105 110 40  41  32  123 10
                p   r   i   n   t   f   (   "   h   e   l   l   o   ,       w   o   r   l   d   \   n   "   )   ;
32  32  32  32  112 114 105 110 116 102 40  34  104 101 108 108 111 44  32  119 111 114 108 100 92  110 34  41  59  10
                r   e   t   u   r   n       0   ;
32  32  32  32  114 101 116 117 114 110 32  48  59  10
}
125 10

实施细节:

您可以选择以所需的任何形式输入(打开文件,命令行管道,函数参数等),并且应将其输出到stdout或从函数返回输出。

注意事项

  • 输出中的每个字符都由一个'\ t'分隔,以允许下面一行中的3位数字对齐(我们假定您的制表符设置为4个或更多)。
  • 换行符显示在按下返回键的行上(请注意示例中的10)
  • '\ t'和'\ n'打印要求不严格。一般而言,您的输出必须看起来令人愉悦(需要向我们展示那些具有美感的外星人),并且如果您可以在保持视觉完整性的同时弯曲前两点,那么您会被原谅。
  • 您可以选择假设最后一行的末尾是否有换行符。

计分

这是代码高尔夫球,因此最短的程序获胜。请注意,即使您的程序不是最短的,但相对于您所使用的语言而言,它却使用了真正巧妙的技巧,许多+1都给您!

祝好运。人类在银河系之间的情报排名取决于您。

注意:请原谅绘图孔。我不是作家:D


8
也许放弃或大大简化了“情节”,就离开了挑战。老实说,我不会读3个背景故事。我将要阅读挑战,因为这就是我的目的。
mbomb007'9

1
@YetiCGN换行符充当换行符(您看不到代表它的字符,但可以看到该换行符),并且仍然需要在ascii版本中显式编写它。就像您正则表达式在源代码中搜索“ \ n”一样。搜索将突出显示的每个地方都是应该写10的地方。是vim中的一个示例(忽略最后一个)。
gowrath '16

26
@ mbomb007 tbh,那是一个非常史诗般的背景故事。我有点喜欢
Maltysen

7
@ mbomb007那些想读书的人,那些不想读书的人可以直接去挑战部分;这就是字幕之美。
gowrath '16

1
我将其解读为“第一个与接触的就是谦虚的PPCG程序员”。
marczellm

Answers:


5

Dyalog APL,14 个字节

获取包含换行序列的字符串列表(10或13 10等)

↑(⊢,[.5]⎕UCS

使包含以下内容的列表具体化

(... 每行返回...

文字本身

,[.5] 在第一个维度之前跟随新维度

⎕UCS所述û nicode Ç haracter 小号等代码点

在线尝试APL!


您不是每行只调用一次,而不是一次接收所有输入吗?
史蒂文H.

1
@StevenH。不,(函数的最右边)包含一个循环,但从整体上来说,它仅被调用一次。请参见f直接在输入上调用的TryAPL示例。如果愿意,每行调用一个函数
2013年

9

Pyth,17 13字节

那些Pyth程序员中的另一个。 抱歉。

新代码要求每行都用引号引起来并进行转义(如果需要打印,则包括换行符),但是在该行和ASCII之间放置了一个额外的换行符。

jjLC9smCMBd.Q

在线尝试!

说明:

           .Q  Evaluate all input lines
      m        For each of those lines:
         Bd     Return the line and
       CM       the line mapped to ASCII characters
     s         Sum all these together to begin alternating between line and mapped line
 jLC9          Join all the characters and numbers in the lines and mapped lines on tabs
j              And join all of those on newlines

我在下面保留旧代码及其解释。

#Jw
jKC9J
jK+CMJT

在线尝试!或使用易于阅读的测试用例

说明:

#                  Until we run into an error:
 Jw                 Read in the next line of input and call it J.
                     (When there is no line of input, error is thrown that ends program.) 

j                  Join: 
    J               all characters in input line
 KC9                and insert tab characters (C9), which we can refer to later as K.
                        (Setting it to a variable doesn't save or lose bytes.)

                   Implicit print that join with trailing newline.

j                  Join:
   CMJ              the mapping of ASCII numbers to characters in the input,
 K                  inserting tab characters in between every number
  +   T             And with a trailing 10 for the newline at the end.

1
我认为您的第一个链接不如第二个链接有效(我认为不会打印新行)。您可能要更新其中的代码。
gowrath's

8

Python 2,105个字节

这使用的方法与OP的答案略有不同。请注意,SO用空格弄乱了我的文字标签。

def f(s):
 o=x=''
 for c in s:
    o+=c+"  ";x+="%s    "%ord(c)
    if"\n"==c:print o[:-1],x;o=x=''
 print o+"\n"+x

在线尝试


x+=ord(c)+" "比短"%s "%ord(c)吗?
DJMcMayhem

@DJMcMayhem您不能将整数附加到字符串。x+=`ord(c)`+" "长度相同
mbomb007'9

8

Vim,86,77击键

:g/^/norm A<C-v><C-v>10<C-v><esc>Yp:s/./\=char2nr(submatch(0))."\t"/g<C-v><cr>k:s/./&\t/g<C-v><cr>
:%s/<C-v><cr>0<cr>

这太长了,但这就是使用vim的eval功能(\=)时得到的。


6
无法分辨您\=是在解释评估功能,还是因为使用评估功能而难过……
AdmBorkBork

2
@timmyD首先。这是我悲伤的脸。D;
DJMcMayhem


6

Perl,> 33 31字节

包括+3 for -F(不能与结合使用-e,代码'也是如此,因此空间也-被计算在内)。

使用STDIN上的输入运行或提供一个或多个文件名作为参数

perl -M5.010 asciidump.pl <<< "Hoi"

asciidump.pl

#!/usr/bin/perl -F
$"=v9;say"@F@{[unpack'W*']}"

如果文本包含选项卡或没有最后的换行符,则输出不美观


5

Pyth,21个字节

j.imjC9d.zmjC9+CMdT.z

这是“那些该死的Pyth程序员”之一的文章;)

一个程序,该程序在STDIN上输入未加引号的多行字符串,然后打印结果。假设所有输入都有尾随换行符。如果希望它不包含尾随的换行符,请<在程序的开头和)_3结尾处添加。

在线尝试

测试用例的输出很难在在线解释器中看到,因此我将其包括在这里:

#   i   n   c   l   u   d   e       <   s   t   d   i   o   .   h   >
35  105 110 99  108 117 100 101 32  60  115 116 100 105 111 46  104 62  10

10
i   n   t       m   a   i   n   t   (   )       {
105 110 116 32  109 97  105 110 116 40  41  32  123 10
                p   r   i   n   t   f   (   "   h   e   l   l   o   ,       w   o   r   l   d   \   n   "   )   ;
32  32  32  32  112 114 105 110 116 102 40  34  104 101 108 108 111 44  32  119 111 114 108 100 92  110 34  41  59  10
                r   e   t   u   r   n       0   ;
32  32  32  32  114 101 116 117 114 110 32  48  59  10
}
125 10

怎么运行的

j.imjC9d.zmjC9+CMdT.z  Program. Input: .z (All of STDIN split on newlines)
     C9                 Yield tab character by taking chr(9)
    j                   Join on tab
   m   d.z             Map that over .z
               CM       Map ord()
              +   T     Append 10
           jC9          Join on tab
          m      d .z  Map that over .z
 .i                    Interleave the results of the two mappings
j                      Join on newlines
                       Implicitly print

您可以通过删除.z和将输入作为行列表来节省2个字节
Maltysen

1
@Maltysen从问题和其他答案来看,我认为分行换行是挑战的一部分。
TheBikingViking

5

C,136个 117个 114字节

#define p(s)while(l[i])printf(s,l[i++]);i=0;puts("")
char l[99];i;f(f){while(fgets(l,99,f)){p("%c\t");p("%d\t");}}

char l[99];i;f(f){while(fgets(l,256,f)){i=0;while(l[i])printf("%c\t",l[i++]);i=0;puts("");while(l[i])printf("%d\t",l[i++]);puts("");}}

可以这样测试

infile;
main(c,v)char**v;
{
    infile=fopen(v[1],"r");
    f(infile);    
}

char**vmain()会有救你2个字符...
亚历克西斯威尔克

嗯,我只在该代码中计算了114个字节。我认为您使用的是CRLF而不是LF(117-> 115),加上尾随换行符(115-> 114)。
TimČas16年

4

PowerShell v2 +,85个字节

gc $args|%{$a=$b='';$_-split'(.)'-ne''|%{$a+="$_`t";$b+="$(+[char]$_)`t"};$a;$b+"10"}

输入是通过文件路径进行的。然后,我们对该文件进行Get-Content别名处理(别名gc),该文件会自动在换行符上分割。我们遍历每一个|%{...}。首先设置$a$b为一个空字符串-这些分别是我们的ASCII字符和代码点。然后-split,我们在每个字符上输入行,保留它(.),并删除空值-ne''(这是.NET regex解析的结果),然后将其发送到另一个循环中。

在每个内部循环中,我们用一个标签将当前字符串起来,`t然后将其添加到上$a。同样$b,除了,我们将显式转换为a char,然后转换为int +

内环以外,我们把所产生的$a,并$b在管道上(用换行标志,因为这永远也不会拿出我们的循环)。Write-Output在程序完成时会隐式收集这些内容。

(在理解到我有一个尾随换行符并且Markdown破坏了制表符的情况下)

PS C:\Tools\Scripts\golfing> .\aliens-only-understand-ascii.ps1 '.\aliens-only-understand-ascii.txt'
#   i   n   c   l   u   d   e       <   s   t   d   i   o   .   h   >   
35  105 110 99  108 117 100 101 32  60  115 116 100 105 111 46  104 62  10

10
i   n   t       m   a   i   n   t   (   )       {   
105 110 116 32  109 97  105 110 116 40  41  32  123 10
                p   r   i   n   t   f   (   "   h   e   l   l   o   w   ,       w   o   r   l   d   \   n   "   )   ;   
32  32  32  32  112 114 105 110 116 102 40  34  104 101 108 108 111 119 44  32  119 111 114 108 100 92  110 34  41  59  10
                r   e   t   u   r   n       0   ;   
32  32  32  32  114 101 116 117 114 110 32  48  59  10
}   
125 10

该死,我只是写了一个PowerShell答案,而设法以某种方式完全错过了这个答案!总是很高兴看到豪华的代表!:)
briantist

4

> <>(鱼),48字节

>i:0(?v::oa=?v9o
2';'oa<.20r  <~p3
o9nv?=0l
voa<

语言闪耀的任务!我敢肯定我可能还会打更多一点,但这已经是漫长的一周了。可能稍后再看。

在线尝试!

另一种在线尝试的方法在我看来看起来更好,但文本换行使输入的内容有些混乱,例如测试用例。


4

PHP,131115字节

只是FGITW,也许我可以进一步改善它。原来,我可以!

131字节的第一个版本:

<?$s=file($argv[1]);foreach($s as$l){$a=str_split(trim($l));echo join(' ',$a).'
';$i=0;while($c=ord($l{$i++}))echo$c.'  ';echo'
';};

文件名作为脚本名称之后的第一个参数提供: php aliens.php helloworld.c

115字节的第二个版本:

function($s){foreach($s as$l){$a=str_split($l);echo join('  ',$a);$i=0;while($c=ord($a[$i++]))echo$c.'  ';echo'
';}};

第一个版本说明了在行尾缺少换行符的问题,但是在进行了进一步说明之后,我们可以省略该代码,并将所有内容放在函数中以节省16个字节。

join(' ',$a)以及中的空格字符echo$c.' '都是制表符= \t。代码中的换行符是有意的。


3

Python 3,89 77字节

基于相同想法的更多高尔夫球版本:

def f(s):
 for a in s:print(*map('{:>4}'.format,[*a,*a.encode()]),end='\n\n')

如果输入中有'\ t',则将其更改49

先前版本:

def f(s):
 for l in s:
  print(*l,sep='\t',end='');print(*l.encode(),sep='\t',end='\n\n')

接受字符串列表,每个字符串均以“ \ n”结尾。


提示:您可以将打印语句保留在for l in sie 的末尾for l in s:print(*l,sep='\t',end='');print(*l.encode(),sep='\t',end='\n\n')
破坏的柠檬

我还没有测试过,但是我想可以用lambda s:'\n\n'.join(*map('{:>4}'.format,[*a,*a.encode()])for a in s)
DJMcMayhem

3

Powershell,56字节

gc $args|%{($a=[char[]]$_)-join"    ";[int[]]$a+10-join"    "}

脚本接受文件路径作为输入。Get-Content自动将输入拆分为字符串数组,该字符串数组在源代码中的换行符上拆分。

在这里,我输入一个foreach,转换为字符数组并将其设置为$ a,将其与制表符连接并打印出来。接下来,但仍然在foreach中,我将字符数组转换为整数数组,追加换行符并再次使用制表符连接。

呼叫看起来像这样:

PS C:\PretendFolder> .\aoua.ps1 ".\aoua.txt"

这是输出样本

#   i   n   c   l   u   d   e       <   s   t   d   i   o   .   h   >
35  105 110 99  108 117 100 101 32  60  115 116 100 105 111 46  104 62  10

10
i   n   t       m   a   i   n   (   )       {
105 110 116 32  109 97  105 110 40  41  32  123 10
                p   r   i   n   t   f   (   "   h   e   l   l   o   ,       w   o   r   l   d   \   n   "   )   ;
32  32  32  32  112 114 105 110 116 102 40  34  104 101 108 108 111 44  32  119 111 114 108 100 92  110 34  41  59  10
                r   e   t   u   r   n       0   ;
32  32  32  32  114 101 116 117 114 110 32  48  59  10
}
125 10

2

JavaScript(ES6),94个字节

s=>s.replace(/(.*)\n?/g,(s,n)=>n&&[...s].join`␉`+`
${[...n].map(c=>c.charCodeAt()).join`␉`}
`)

其中␉表示文字制表符。只要输入不包含制表符,就可以使用。81字节的版本,也要求输入的末尾有换行符:

s=>s.replace(/.*\n/g,s=>[...s].join`␉`+[...s].map(c=>c.charCodeAt()).join`␉`+`
`)

我认为.split().map()可能会赢.replace()。一旦使用反引号对转义字符进行了优化,则该长度应为85字节:(s=>s.split('\n').map(c=>(s=[...c]).join('\t')+'\n'+s.map(c=>c.charCodeAt()).join('\t')).join('\n')对不起,我不知道注释中是否可以包括反引号。)
Arnauld

@Arnauld不适用于(例如)换行符。另外,要在评论中包含反引号,请在反引号之前加上反斜杠。
尼尔

2

C#,64 63字节

s=>{foreach(int c in s+(s=""))s+=c+(10==c?"\n":"    ");return s;};

使用实际的制表符而不是-1个字节\t。注意:在下面的非高尔夫版本中,上方为4个空格,在上方为2个空格。

取消高尔夫:

/*Func<string, string> Lambda =*/ s =>
{
    // Enumerate the ascii (int) values of the chars in s, 
    // but at the same time set input s to "" to use at the output var.
    // +(s="")   is 2 bytes less than   var o="";
    foreach (int c in s + (s=""))
        // Append the string representation of the ascii value,
        // Append new line if c was new line, otherwise append tab. 
        s += c + (10==c ? "\n" : "  ");
    return s;
};

结果:

(注意:\r\n当我粘贴输入内容时,Visual Studio会使用新行,因此13 10输出行的结尾)

Input:

#include <stdio.h>

int maint() {
    printf("hello, world\n");
    return 0;
}

Output:

35  105 110 99  108 117 100 101 32  60  115 116 100 105 111 46  104 62  13  10
13  10
105 110 116 32  109 97  105 110 116 40  41  32  123 13  10
32  32  32  32  112 114 105 110 116 102 40  34  104 101 108 108 111 44  32  119 111 114 108 100 92  110 34  41  59  13  10
32  32  32  32  114 101 116 117 114 110 32  48  59  13  10
125 

2

CJam,27个字节

qN/{_1/9c*N+\{is9c}%+}%AN+*

在线尝试!

说明

q       e# Take the whole input
N/      e# Split on newlines
{       e# Map this block to every line:
_        e# Duplicate
1/       e# Split into characters
9c*      e# Join with tabs (ASCII code 9)
N+       e# Append a newline
\        e# Swap top elements
{is9c}%  e# Map each character to its ASCII code plus a tab character
+        e# Concatenate the two lines
}%      e# (end of block)
AN+*    e# Join with "10" plus a newline

1/s是不必要的。
Martin Ender

2

PowerShell,61 59字节

gc m|%{$b="$_
"[0..$_.Length]
$b-join'    '
[int[]]$b-join' '}

注意事项:

  • m当前目录中命名的文件中读取输入。
  • 所有换行符(包括嵌入在字符串中的第一个$_换行符)仅是文字换行(0xA),因此每个换行符。
  • -join运算符之后的字符串内容都是单个制表符(无论在此处如何呈现)。

不打高尔夫球

Get-Content m | ForEach-Object -Process { # Read the file line by line
    $b = "$_`n"[0..$_.Length]   # Line by line processing strips line endings, so add a newline
                                # Index operator on a [string] returns a [char], or given a [range], a [char[]]
                                # Using $_.Length automatically accounts for the extra linebreak (0 based index)
    $b -join "`t"               # PowerShell displays [char] as the printable character by default, so join the array with a tab
    [int[]]$b -join "`t"        # We need to convert the [char]s to an [int]s so we can display it as a number
                                # So cast the [char[]] as [int[]], then join with tab again

}

您的代码正在打印ascii 13,换行符,而不是10,回车符,如挑战的输出示例所示
Chirishman

@Chirishman PowerShell确实仅支持将ASCII 10用于.ps1文件中的换行符,但是在大多数文本编辑器的Windows中,这样做非常棘手。使用SCiTE或Notepad ++或其他支持行尾的编辑器,可以确保它使用的是UNIX结尾。一旦确定文件不包含13个文件,它将打印10个文件。
briantist 2016年

0

Java,202字节

s->{for(String g : s.split("\n")){g.chars().forEach(c->System.out.print((char)c+"   "));System.out.println();g.chars().forEach(c->System.out.print(c+(c<10?"  ":c<100?"  ":" ")));System.out.println();}};

我什至不愿意将其缩短。


0

Haskell-71个字节

f q=unlines[(x>>=(++"\t").show.ord)++'\n':intersperse '\t'x|x<-lines q]

-1

Python 3,92 97107字节

对于列表中的i(open(input())。read()。split(“ \ n”)):对于i中的j:print(i +“ \ n” + ord(j))

p=print
for i in list(open(input()).read().split("\n"))
    s=t=''
    for j in i:
        r=str(ord(j))
        s+=j+' '*len(r)
        t+=r+' '
    p(s)
    p(t)

这未经测试,但应该可以。

感谢@gowrath指出该代码未按照问题所指定的那样执行。


为什么不?所有input()命令正在执行的操作是获取要打开的文件的名称。
sonrad10年

@gowrath哦,好的。
sonrad10年

这不会像问题说明中那样覆盖文本和ascii输出。只是打印数字。
gowrath

@gowrath谢谢,我会尽快解决。
sonrad10年

@ sonrad10删除,直到修复。
mbomb007'9
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.