代码高尔夫:连接点

发布于 2024-08-26 17:55:13 字数 5273 浏览 6 评论 0原文

您可能还记得小时候的这些图画,但现在是时候让计算机绘制它们了(以完整的 ASCII 格式)。玩得开心!

描述:

输入是描述“字段”的多行(以换行符结尾)。该字段中散布着“数字”(由空格分隔)。所有行都可以被认为是相同的长度(您可以在末尾添加空格)。

  • 数字始终从 1 开始
  • 它们遵循自然数的顺序:每个“下一个数字”都以 1 递增
  • 每个数字的左右两侧(至少)有一个空格

任务:

绘制这些数字之间的线条按其自然顺序排列 (1 -> 2 -> 3 -> ...N)(假设 N <= 99)具有以下特征:

  1. 用 '+' 字符
  2. 表示水平线:使用 '-'
  3. 表示垂直线:使用 '|'
  4. 向左、向下或向右和向上:/
  5. 向左、向上或向右、向下:\

重要说明:

  1. 当绘制类型 4 和 5 的线时,您可以假设(给定与坐标连接的点) x1, y1 和 x2, y2) 表示距离(x1,x2) == 距离(y1,y2)。或者换句话说(正如用户 jball 评论的那样):“不水平或垂直对齐的连续元素总是与斜杠或反斜杠的斜率对齐”。

  2. 遵循点连接的顺序很重要(新线可以删除旧线)。

    遵循

-- 示例输入 1 --

                                  8 

                                  7  6 
                      10       9       

                                        5            

                                     3  4        
                 11 

                   12                       13    
          1                          2                     

-- 示例输出 1 --

                                 +                                
                                /|                                
                               / +--+                             
                     +--------+      \                            
                    /                 \                           
                   /                   +                          
                  /                    |                          
                 /                  +--+                          
                +                   |                             
                 \                  |                             
                  +------------------------+                      
         +--------------------------+        

-- 示例输入 2 --

                        64          
                        63              



                    62 61                             
               1  65                                   
                 66    57 58                               
               2      56  59               45                
                   67  55                  46              
             3                               44           
                         54  60            47              
                          53 52   49      48              
             4                51 50       43            

           5                                42              
                                            41               
           6              23                                 
                          22 25  26       40              
                      20 21 24            34                 
              7 13 12                    33                    
                    19              27  32                     
                14                        35               
           8   15                                           
                16                                         
                                   39                        
                17  18         28  31 36                  
               9                     38                       
                10 11          29  30 37                       

-- 示例输出 2 -- (独角兽参考)

                       +        
                      /+      
                     //          
                    //        
                   //           
                  /+--+        
              +  +     \         
              | +     +-\+          
              +  \   +   \                +         
             /    +   +   \               +\    
            +          \   \              | +       
            |           +   +             +/           
            |            +--+    +-------+/               
            +                +--+        +              
           /                              \              
          +                                +               
          |                                +                 
          +              +                /             
           \             +\ +---+        +           
            \        +--+  +     \      /+              
             + +--+ /             \    /+|             
            /  |  |+               +  /+ |                 
           /   +  ||              /  //  +            
          +   +   ||             /  //  /                
           \   +  ||            /  //  /              
            \  |  ||           /  +/  /                  
             \ +---+          +   +\ +                  
              +   |           |   | +|                 
               +--+           +---+  +               

获胜者:< /strong>

最短解决方案(按代码字符数)。可以通过标准输入读取输入。

You may remember these drawings from when you were a child, but now it's time to let the computer draw them (in full ascii splendour). Have fun!

Description:

The input are multiple lines (terminated by a newline) which describe a 'field'. There are 'numbers' scattered across this field (seperated by whitespace). All lines can be considered to be the same length (you can pad spaces to the end).

  • the numbers always start at 1
  • they follow the ordering of the natural numbers: every 'next number' is incremented with 1
  • every number is surrounded by (at least) one whitespace on its left and right

Task:

Draw lines between these numbers in their natural order
(1 -> 2 -> 3 -> ...N) (assume N <= 99) with the following characteristics:

  1. replace a number with a '+' character
  2. for horizontal lines: use '-'
  3. for vertical lines: use '|'
  4. going left and down or right and up: /
  5. going left and up or right and down: \

Important notes:

  1. When drawing lines of type 4 and 5 you can assume (given the points to connect with coordinates x1, y1 and x2, y2) that distance(x1,x2) == distance(y1,y2). Or in other words (as user jball commented): "consecutive elements that are not horizontally or vertically aligned always align to the slope of the slash or backslash".

  2. It is important to follow the order in which the dots are connected (newer lines can strike out older lines).

-- Sample input 1 --

                                  8 

                                  7  6 
                      10       9       

                                        5            

                                     3  4        
                 11 

                   12                       13    
          1                          2                     

-- Sample output 1 --

                                 +                                
                                /|                                
                               / +--+                             
                     +--------+      \                            
                    /                 \                           
                   /                   +                          
                  /                    |                          
                 /                  +--+                          
                +                   |                             
                 \                  |                             
                  +------------------------+                      
         +--------------------------+        

-- Sample input 2 --

                        64          
                        63              



                    62 61                             
               1  65                                   
                 66    57 58                               
               2      56  59               45                
                   67  55                  46              
             3                               44           
                         54  60            47              
                          53 52   49      48              
             4                51 50       43            

           5                                42              
                                            41               
           6              23                                 
                          22 25  26       40              
                      20 21 24            34                 
              7 13 12                    33                    
                    19              27  32                     
                14                        35               
           8   15                                           
                16                                         
                                   39                        
                17  18         28  31 36                  
               9                     38                       
                10 11          29  30 37                       

-- Sample output 2 -- (unicorn reference)

                       +        
                      /+      
                     //          
                    //        
                   //           
                  /+--+        
              +  +     \         
              | +     +-\+          
              +  \   +   \                +         
             /    +   +   \               +\    
            +          \   \              | +       
            |           +   +             +/           
            |            +--+    +-------+/               
            +                +--+        +              
           /                              \              
          +                                +               
          |                                +                 
          +              +                /             
           \             +\ +---+        +           
            \        +--+  +     \      /+              
             + +--+ /             \    /+|             
            /  |  |+               +  /+ |                 
           /   +  ||              /  //  +            
          +   +   ||             /  //  /                
           \   +  ||            /  //  /              
            \  |  ||           /  +/  /                  
             \ +---+          +   +\ +                  
              +   |           |   | +|                 
               +--+           +---+  +               

Winner:

Shortest solution (by code character count). Input can be read via standard input.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

榕城若虚 2024-09-02 17:55:13

Commodore 64 BASIC - 313 个字符

编辑:高尔夫版本见下文

PET 图形、POKEPEEK 以及所有内容:)

它适合单个屏幕:)

该程序直接在屏幕内存中运行,因此您只需继续,清除屏幕,放置点,然后输入RUN:

Input

你必须等待一分钟左右,它才能找到点,然后它开始画画。它并不快 - 你实际上可以看到正在绘制的线条,但这是最酷的部分:)

Output

高尔夫版本:

Commodore BASIC 似乎是一种很棒的高尔夫语言,因为它不需要空格:)您还可以通过输入未移动的第一个字母,然后输入移动的第二个字母来缩短大多数命令。例如,POKE 可以输入为 P[SHIFT+O],它在屏幕上显示为 P┌

高尔夫版本

Commodore 64 BASIC - 313 chars

EDIT: See below for the golfed version

A little trip down the memory lane with PET graphics, POKEs and PEEKs and everything :)

It fits in a single screen:)

The program operates directly in the screen memory, so you just go ahead, clear the screen, place your dots, and type RUN:

Input

You have to wait a minute or so while it finds the dots and then it starts to draw. It isn't fast - you can actually see the lines being drawn, but that's the coolest part :)

Output

Golfed version:

Commodore BASIC seems like a great language for golfing, because it doesn't require whitespace :) You can also shorten most of the commands by entering an unshifted first letter followed by a shifted second letter. For example, POKE can be typed as P[SHIFT+O], which appears as P┌ on the screen:

Golfed version

听闻余生 2024-09-02 17:55:13

Perl,222 字符 (211)

Perl,384 365 276 273 253 < Strike>225 222 218 211 个字符(比赛结束时为 222 个)。换行符仅用于“可读性”,不包含在字符数中。

最后编辑:不再覆盖 $",并直接打印 @S

    $_=join'',@S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>;
    while(/\b$n /){$S[$q=$-[0]]='+';($P,$Q)=sort{$a-$b}$q,$p||$q;
    for(qw'\98 |97 /96 -1'){/\D/;$S[$P]=
amp;until($Q-$P)%

说明:

$_=join'',@S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>;

如果所有行的长度相同(例如 97 个字符),此任务会更容易。
该语句获取每一行输入,将行尾字符替换为
96 个空格,然后将前 96 个字符加上换行符推入数组 @S 中。
请注意,我们还设置了 $n=1,因为 1 是我们要查找的第一个数字
输入。
join 语句从数组 @S 创建单个字符串。
使用标量变量$_进行模式匹配更方便,使用数组@S对图片进行更新更方便。

while(/\b$n /){

在变量 $_ 中搜索数字 $n。在 Perl 中评估正则表达式
有几个副作用。一种是设置特殊变量 $-[0] 为匹配字符串中匹配模式的开头位置。这为我们提供了数字 $n 在字符串 $_ 以及数组 @S 中的位置。

当然,当 $n 足够高以至于我们无法在输入中找到它时,循环就会结束。

    $S[$q=$-[0]]='+';

$q 为数字 $n 在字符串 $_ 和数组 @S 中的位置,
并在该位置分配字符“+”。

        $P=($p||=$q)+$q-($Q=$q>$p?$q:$p)
        ($P,$Q)=sort{$a-$b}$p||$q,$q;

第一次循环时,将 $p 设置为 $q。之后
第一次,$p 将保存 $q前一个值(其中
将参考前一个数字在输入中的位置)。
分配 $P$Q 使得 $P=min($p,$q< /代码>),
$Q=max($p,$q)

    for(qw'\98 |97 /96 -1'){

通过构造,连续的数字要么

  • 由垂直线连接。由于输入已构建
    每行有 97 个字符,这种情况意味着
    $p-$q 能被 97 整除。

  • “与反斜杠的斜率对齐”,这将使
    $p-$q 能被 98 整除

  • “与正斜杠的斜率对齐”,这将使
    $p-$q 能被 96 整除

  • 在同一水平线上

此列表的元素对可能的位置数进行编码
线段之间,以及对该线段进行编码的字符。

        /\D/;

另一个简单的正则表达式评估。作为副作用,它设置了
特殊变量 $&MATCH 变量)线段
字符(\ | /-)和 $'POSTMATCH 变量)到
列表元素中编码的数字(98 97 96 或 1)。

        $S[$P]=
amp;until($Q-$P)%

该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q

    $n++;$p=$q

为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。

s/\d/ /,print for@S

输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

||$Q<=($P+=

说明:


如果所有行的长度相同(例如 97 个字符),此任务会更容易。
该语句获取每一行输入,将行尾字符替换为
96 个空格,然后将前 96 个字符加上换行符推入数组 @S 中。
请注意,我们还设置了 $n=1,因为 1 是我们要查找的第一个数字
输入。
join 语句从数组 @S 创建单个字符串。
使用标量变量$_进行模式匹配更方便,使用数组@S对图片进行更新更方便。


在变量 $_ 中搜索数字 $n。在 Perl 中评估正则表达式
有几个副作用。一种是设置特殊变量 $-[0] 为匹配字符串中匹配模式的开头位置。这为我们提供了数字 $n 在字符串 $_ 以及数组 @S 中的位置。

当然,当 $n 足够高以至于我们无法在输入中找到它时,循环就会结束。


$q 为数字 $n 在字符串 $_ 和数组 @S 中的位置,
并在该位置分配字符“+”。


第一次循环时,将 $p 设置为 $q。之后
第一次,$p 将保存 $q前一个值(其中
将参考前一个数字在输入中的位置)。
分配 $P$Q 使得 $P=min($p,$q< /代码>),
$Q=max($p,$q)


通过构造,连续的数字要么

  • 由垂直线连接。由于输入已构建
    每行有 97 个字符,这种情况意味着
    $p-$q 能被 97 整除。

  • “与反斜杠的斜率对齐”,这将使
    $p-$q 能被 98 整除

  • “与正斜杠的斜率对齐”,这将使
    $p-$q 能被 96 整除

  • 在同一水平线上

此列表的元素对可能的位置数进行编码
线段之间,以及对该线段进行编码的字符。


另一个简单的正则表达式评估。作为副作用,它设置了
特殊变量 $&MATCH 变量)线段
字符(\ | /-)和 $'POSTMATCH 变量)到
列表元素中编码的数字(98 97 96 或 1)。


该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q


为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。


输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

)} $n++;$p=$q}s/\d/ /,print for@S

说明:


如果所有行的长度相同(例如 97 个字符),此任务会更容易。
该语句获取每一行输入,将行尾字符替换为
96 个空格,然后将前 96 个字符加上换行符推入数组 @S 中。
请注意,我们还设置了 $n=1,因为 1 是我们要查找的第一个数字
输入。
join 语句从数组 @S 创建单个字符串。
使用标量变量$_进行模式匹配更方便,使用数组@S对图片进行更新更方便。


在变量 $_ 中搜索数字 $n。在 Perl 中评估正则表达式
有几个副作用。一种是设置特殊变量 $-[0] 为匹配字符串中匹配模式的开头位置。这为我们提供了数字 $n 在字符串 $_ 以及数组 @S 中的位置。

当然,当 $n 足够高以至于我们无法在输入中找到它时,循环就会结束。


$q 为数字 $n 在字符串 $_ 和数组 @S 中的位置,
并在该位置分配字符“+”。


第一次循环时,将 $p 设置为 $q。之后
第一次,$p 将保存 $q前一个值(其中
将参考前一个数字在输入中的位置)。
分配 $P$Q 使得 $P=min($p,$q< /代码>),
$Q=max($p,$q)


通过构造,连续的数字要么

  • 由垂直线连接。由于输入已构建
    每行有 97 个字符,这种情况意味着
    $p-$q 能被 97 整除。

  • “与反斜杠的斜率对齐”,这将使
    $p-$q 能被 98 整除

  • “与正斜杠的斜率对齐”,这将使
    $p-$q 能被 96 整除

  • 在同一水平线上

此列表的元素对可能的位置数进行编码
线段之间,以及对该线段进行编码的字符。


另一个简单的正则表达式评估。作为副作用,它设置了
特殊变量 $&MATCH 变量)线段
字符(\ | /-)和 $'POSTMATCH 变量)到
列表元素中编码的数字(98 97 96 或 1)。


该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q


为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。


输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

||$Q<=($P+=

该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q


为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。


输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

||$Q<=($P+=

说明:


如果所有行的长度相同(例如 97 个字符),此任务会更容易。
该语句获取每一行输入,将行尾字符替换为
96 个空格,然后将前 96 个字符加上换行符推入数组 @S 中。
请注意,我们还设置了 $n=1,因为 1 是我们要查找的第一个数字
输入。
join 语句从数组 @S 创建单个字符串。
使用标量变量$_进行模式匹配更方便,使用数组@S对图片进行更新更方便。


在变量 $_ 中搜索数字 $n。在 Perl 中评估正则表达式
有几个副作用。一种是设置特殊变量 $-[0] 为匹配字符串中匹配模式的开头位置。这为我们提供了数字 $n 在字符串 $_ 以及数组 @S 中的位置。

当然,当 $n 足够高以至于我们无法在输入中找到它时,循环就会结束。


$q 为数字 $n 在字符串 $_ 和数组 @S 中的位置,
并在该位置分配字符“+”。


第一次循环时,将 $p 设置为 $q。之后
第一次,$p 将保存 $q前一个值(其中
将参考前一个数字在输入中的位置)。
分配 $P$Q 使得 $P=min($p,$q< /代码>),
$Q=max($p,$q)


通过构造,连续的数字要么

  • 由垂直线连接。由于输入已构建
    每行有 97 个字符,这种情况意味着
    $p-$q 能被 97 整除。

  • “与反斜杠的斜率对齐”,这将使
    $p-$q 能被 98 整除

  • “与正斜杠的斜率对齐”,这将使
    $p-$q 能被 96 整除

  • 在同一水平线上

此列表的元素对可能的位置数进行编码
线段之间,以及对该线段进行编码的字符。


另一个简单的正则表达式评估。作为副作用,它设置了
特殊变量 $&MATCH 变量)线段
字符(\ | /-)和 $'POSTMATCH 变量)到
列表元素中编码的数字(98 97 96 或 1)。


该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q


为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。


输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

)} $n++;$p=$q}s/\d/ /,print for@S

说明:

如果所有行的长度相同(例如 97 个字符),此任务会更容易。
该语句获取每一行输入,将行尾字符替换为
96 个空格,然后将前 96 个字符加上换行符推入数组 @S 中。
请注意,我们还设置了 $n=1,因为 1 是我们要查找的第一个数字
输入。
join 语句从数组 @S 创建单个字符串。
使用标量变量$_进行模式匹配更方便,使用数组@S对图片进行更新更方便。

在变量 $_ 中搜索数字 $n。在 Perl 中评估正则表达式
有几个副作用。一种是设置特殊变量 $-[0] 为匹配字符串中匹配模式的开头位置。这为我们提供了数字 $n 在字符串 $_ 以及数组 @S 中的位置。

当然,当 $n 足够高以至于我们无法在输入中找到它时,循环就会结束。

$q 为数字 $n 在字符串 $_ 和数组 @S 中的位置,
并在该位置分配字符“+”。

第一次循环时,将 $p 设置为 $q。之后
第一次,$p 将保存 $q前一个值(其中
将参考前一个数字在输入中的位置)。
分配 $P$Q 使得 $P=min($p,$q< /代码>),
$Q=max($p,$q)

通过构造,连续的数字要么

  • 由垂直线连接。由于输入已构建
    每行有 97 个字符,这种情况意味着
    $p-$q 能被 97 整除。

  • “与反斜杠的斜率对齐”,这将使
    $p-$q 能被 98 整除

  • “与正斜杠的斜率对齐”,这将使
    $p-$q 能被 96 整除

  • 在同一水平线上

此列表的元素对可能的位置数进行编码
线段之间,以及对该线段进行编码的字符。

另一个简单的正则表达式评估。作为副作用,它设置了
特殊变量 $&MATCH 变量)线段
字符(\ | /-)和 $'POSTMATCH 变量)到
列表元素中编码的数字(98 97 96 或 1)。

该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q

为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。

输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

)

该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q

为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。

输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

||$Q<=($P+=

说明:

如果所有行的长度相同(例如 97 个字符),此任务会更容易。
该语句获取每一行输入,将行尾字符替换为
96 个空格,然后将前 96 个字符加上换行符推入数组 @S 中。
请注意,我们还设置了 $n=1,因为 1 是我们要查找的第一个数字
输入。
join 语句从数组 @S 创建单个字符串。
使用标量变量$_进行模式匹配更方便,使用数组@S对图片进行更新更方便。

在变量 $_ 中搜索数字 $n。在 Perl 中评估正则表达式
有几个副作用。一种是设置特殊变量 $-[0] 为匹配字符串中匹配模式的开头位置。这为我们提供了数字 $n 在字符串 $_ 以及数组 @S 中的位置。

当然,当 $n 足够高以至于我们无法在输入中找到它时,循环就会结束。

$q 为数字 $n 在字符串 $_ 和数组 @S 中的位置,
并在该位置分配字符“+”。

第一次循环时,将 $p 设置为 $q。之后
第一次,$p 将保存 $q前一个值(其中
将参考前一个数字在输入中的位置)。
分配 $P$Q 使得 $P=min($p,$q< /代码>),
$Q=max($p,$q)

通过构造,连续的数字要么

  • 由垂直线连接。由于输入已构建
    每行有 97 个字符,这种情况意味着
    $p-$q 能被 97 整除。

  • “与反斜杠的斜率对齐”,这将使
    $p-$q 能被 98 整除

  • “与正斜杠的斜率对齐”,这将使
    $p-$q 能被 96 整除

  • 在同一水平线上

此列表的元素对可能的位置数进行编码
线段之间,以及对该线段进行编码的字符。

另一个简单的正则表达式评估。作为副作用,它设置了
特殊变量 $&MATCH 变量)线段
字符(\ | /-)和 $'POSTMATCH 变量)到
列表元素中编码的数字(98 97 96 或 1)。

该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q

为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。

输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

)} $n++;$p=$q}s/\d/ /,print for@S

说明:

如果所有行的长度相同(例如 97 个字符),此任务会更容易。
该语句获取每一行输入,将行尾字符替换为
96 个空格,然后将前 96 个字符加上换行符推入数组 @S 中。
请注意,我们还设置了 $n=1,因为 1 是我们要查找的第一个数字
输入。
join 语句从数组 @S 创建单个字符串。
使用标量变量$_进行模式匹配更方便,使用数组@S对图片进行更新更方便。

在变量 $_ 中搜索数字 $n。在 Perl 中评估正则表达式
有几个副作用。一种是设置特殊变量 $-[0] 为匹配字符串中匹配模式的开头位置。这为我们提供了数字 $n 在字符串 $_ 以及数组 @S 中的位置。

当然,当 $n 足够高以至于我们无法在输入中找到它时,循环就会结束。

$q 为数字 $n 在字符串 $_ 和数组 @S 中的位置,
并在该位置分配字符“+”。

第一次循环时,将 $p 设置为 $q。之后
第一次,$p 将保存 $q前一个值(其中
将参考前一个数字在输入中的位置)。
分配 $P$Q 使得 $P=min($p,$q< /代码>),
$Q=max($p,$q)

通过构造,连续的数字要么

  • 由垂直线连接。由于输入已构建
    每行有 97 个字符,这种情况意味着
    $p-$q 能被 97 整除。

  • “与反斜杠的斜率对齐”,这将使
    $p-$q 能被 98 整除

  • “与正斜杠的斜率对齐”,这将使
    $p-$q 能被 96 整除

  • 在同一水平线上

此列表的元素对可能的位置数进行编码
线段之间,以及对该线段进行编码的字符。

另一个简单的正则表达式评估。作为副作用,它设置了
特殊变量 $&MATCH 变量)线段
字符(\ | /-)和 $'POSTMATCH 变量)到
列表元素中编码的数字(98 97 96 或 1)。

该语句绘制两个数字之间的线段。
如果 $Q-$P 能被 $' 整除,则继续将 $P 增加 $'
并将字符$&分配给$S[$P],直到$P到达$Q
更具体地说,例如如果 $Q-$P 能被 97 整除,那么
$P 加 97 并设置 $S[$P]='|'。重复直到$P>=$Q

为循环的下一次迭代做好准备。将 $n 增加到
要在输入中搜索的下一个数字,并让 $p 保存
前一个数字的位置。

输出数组,转换任何剩余的数字(从双
输入中的数字标识符,我们只覆盖第一个
数字带“+”)到空格。

Perl, 222 char (211)

Perl, 384 365 276 273 253 225 222 218 211 chars (222 when contest ended). Newlines are for "readability" only and are not included in the character count.

Last edit: no longer overwriting $", and printing @S directly

    $_=join'',@S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>;
    while(/\b$n /){$S[$q=$-[0]]='+';($P,$Q)=sort{$a-$b}$q,$p||$q;
    for(qw'\98 |97 /96 -1'){/\D/;$S[$P]=
amp;until($Q-$P)%

Explanation:

$_=join'',@S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>;

This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array @S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array @S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array @S for making updates to the picture.

while(/\b$n /){

Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array @S.

Of course, the loop will end when $n is high enough that we can't find it in the input.

    $S[$q=$-[0]]='+';

Let $q be the position of the number $n in the string $_ and the array @S,
and assign the character '+' at that position.

        $P=($p||=$q)+$q-($Q=$q>$p?$q:$p)
        ($P,$Q)=sort{$a-$b}$p||$q,$q;

The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)

    for(qw'\98 |97 /96 -1'){

By construction, consecutive numbers are either

  • connected by a vertical line. Since the input is constructed
    to have 97 characters on each line, this case means that
    $p-$q is divisible by 97.

  • "aligned to the slope of a backslash", which would make
    $p-$q divisible by 98

  • "aligned to the slope of a forward slash", which would make
    $p-$q divisible by 96

  • on the same horizontal line

The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.

        /\D/;

Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.

        $S[$P]=
amp;until($Q-$P)%

This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.

    $n++;$p=$q

Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.

s/\d/ /,print for@S

Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

||$Q<=($P+=

Explanation:


This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array @S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array @S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array @S for making updates to the picture.


Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array @S.

Of course, the loop will end when $n is high enough that we can't find it in the input.


Let $q be the position of the number $n in the string $_ and the array @S,
and assign the character '+' at that position.


The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)


By construction, consecutive numbers are either

  • connected by a vertical line. Since the input is constructed
    to have 97 characters on each line, this case means that
    $p-$q is divisible by 97.

  • "aligned to the slope of a backslash", which would make
    $p-$q divisible by 98

  • "aligned to the slope of a forward slash", which would make
    $p-$q divisible by 96

  • on the same horizontal line

The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.


Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.


This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.


Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.


Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

)} $n++;$p=$q}s/\d/ /,print for@S

Explanation:


This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array @S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array @S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array @S for making updates to the picture.


Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array @S.

Of course, the loop will end when $n is high enough that we can't find it in the input.


Let $q be the position of the number $n in the string $_ and the array @S,
and assign the character '+' at that position.


The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)


By construction, consecutive numbers are either

  • connected by a vertical line. Since the input is constructed
    to have 97 characters on each line, this case means that
    $p-$q is divisible by 97.

  • "aligned to the slope of a backslash", which would make
    $p-$q divisible by 98

  • "aligned to the slope of a forward slash", which would make
    $p-$q divisible by 96

  • on the same horizontal line

The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.


Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.


This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.


Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.


Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

||$Q<=($P+=

This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.


Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.


Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

||$Q<=($P+=

Explanation:


This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array @S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array @S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array @S for making updates to the picture.


Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array @S.

Of course, the loop will end when $n is high enough that we can't find it in the input.


Let $q be the position of the number $n in the string $_ and the array @S,
and assign the character '+' at that position.


The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)


By construction, consecutive numbers are either

  • connected by a vertical line. Since the input is constructed
    to have 97 characters on each line, this case means that
    $p-$q is divisible by 97.

  • "aligned to the slope of a backslash", which would make
    $p-$q divisible by 98

  • "aligned to the slope of a forward slash", which would make
    $p-$q divisible by 96

  • on the same horizontal line

The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.


Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.


This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.


Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.


Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

)} $n++;$p=$q}s/\d/ /,print for@S

Explanation:

This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array @S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array @S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array @S for making updates to the picture.

Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array @S.

Of course, the loop will end when $n is high enough that we can't find it in the input.

Let $q be the position of the number $n in the string $_ and the array @S,
and assign the character '+' at that position.

The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)

By construction, consecutive numbers are either

  • connected by a vertical line. Since the input is constructed
    to have 97 characters on each line, this case means that
    $p-$q is divisible by 97.

  • "aligned to the slope of a backslash", which would make
    $p-$q divisible by 98

  • "aligned to the slope of a forward slash", which would make
    $p-$q divisible by 96

  • on the same horizontal line

The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.

Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.

This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.

Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.

Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

)

This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.

Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.

Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

||$Q<=($P+=

Explanation:

This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array @S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array @S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array @S for making updates to the picture.

Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array @S.

Of course, the loop will end when $n is high enough that we can't find it in the input.

Let $q be the position of the number $n in the string $_ and the array @S,
and assign the character '+' at that position.

The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)

By construction, consecutive numbers are either

  • connected by a vertical line. Since the input is constructed
    to have 97 characters on each line, this case means that
    $p-$q is divisible by 97.

  • "aligned to the slope of a backslash", which would make
    $p-$q divisible by 98

  • "aligned to the slope of a forward slash", which would make
    $p-$q divisible by 96

  • on the same horizontal line

The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.

Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.

This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.

Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.

Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

)} $n++;$p=$q}s/\d/ /,print for@S

Explanation:

This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array @S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array @S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array @S for making updates to the picture.

Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array @S.

Of course, the loop will end when $n is high enough that we can't find it in the input.

Let $q be the position of the number $n in the string $_ and the array @S,
and assign the character '+' at that position.

The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)

By construction, consecutive numbers are either

  • connected by a vertical line. Since the input is constructed
    to have 97 characters on each line, this case means that
    $p-$q is divisible by 97.

  • "aligned to the slope of a backslash", which would make
    $p-$q divisible by 98

  • "aligned to the slope of a forward slash", which would make
    $p-$q divisible by 96

  • on the same horizontal line

The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.

Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.

This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.

Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.

Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.

喜你已久 2024-09-02 17:55:13

MS-DOS Batch(是的,你没看错!)

我经常听到(或读到)人们说批处理不是很强大,你不能用它们做太多事情,我对他们说,看吧,BATCH 的力量!

实际脚本 (script.bat):

set file=%~1
call :FindNextNum 1

for /F "tokens=2 delims=:" %%i IN ('find /c /V "" "%file%"') DO set /a totalLines=%%i

set maxLen=0
for /F "delims=" %%i IN (%file%) DO (
 call :CountChars "%%i"
 if /i !charCount! gtr !maxLen! set maxLen=!charCount!
)

for /L %%i IN (0,1,%totalLines%) DO set "final_%%i=" & for /L %%j IN (0,1,%maxLen%) DO set "final_%%i=!final_%%i! "

:MainLoop
set currLineNum=%lineNum%
set currCol=%linePos%
set currNum=%nextNum%

set /a targetNum=%currNum%+1
call :FindNextNum %targetNum%
if "%nextNum%"=="" goto MainEnd

REM echo %currNum% -^> %nextNum%
if /I %currLineNum% lss %lineNum% (
call :DrawLine %currCol% %currLineNum% %linePos% %lineNum%
) else (
call :DrawLine %linePos% %lineNum% %currCol% %currLineNum%
)

goto MainLoop

:MainEnd
for /L %%i IN (0,1,%totalLines%) DO echo.!final_%%i!
goto:eof


:DrawLine

if /I %2 equ %4 goto:DrawHoriz
set "char=" & set "pos=%1" & set "inc=0"
if /I %1 LSS %3 set "char=\" & set "pos=%1" & set "inc=1"
if /I %1 GTR %3 set "char=/" & set "pos=%1" & set "inc=-1"
for /L %%i IN (%2,1,%4) DO call :DrawChar %%i !pos! %char% & set /a "pos+=%inc%"
goto:DrawEnds

:DrawHoriz
set "start=%1+1" & set "end=%3"
if /I %start% gtr %end% set "start=%3+1" & set "end=%1"
set /a lineEnd=%end%+1
set lineEnd=!final_%2:~%lineEnd%!
for /L %%i IN (%start%,1,%end%) DO set final_%2=!final_%2:~0,%%i!-
set final_%2=!final_%2!!lineEnd!

:DrawEnds
call :DrawChar %2 %1 +
call :DrawChar %4 %3 +
goto:eof

:DrawChar 
set /a skip2=%2+1
if "%3"=="" (
set final_%1=!final_%1:~0,%2!^|!final_%1:~%skip2%!
) else (
set final_%1=!final_%1:~0,%2!%3!final_%1:~%skip2%!
)
goto:eof


:CountChars
set charCount=0
set val=%~1
:CountChars_loop
if not "%val:~1%"=="" (
set /a charCount+=1
set val=!val:~1!
goto CountChars_loop
)
goto:eof



:FindNextNum
for /F "delims=" %%i IN ('type "%file%" ^| find /V /N ""') DO (
for /F "tokens=1,2 delims=[]" %%j IN ("%%i") DO (
    set /a lineNum=%%j-1
    call :FindNext_internal "%%k" %1

    if /I !nextNum! equ %1 goto :eof
)
)

goto:eof

:FindNext_internal
set currLine=%~1
set linePos=0
:FindNext_internal_loop
call :NextNumInLine "%currLine%"
set /a linePos+=%spaceInterval%
if "%nextNum%"=="" goto :EOF
if /I %nextNum% equ %2 goto :EOF
set /a spaceInterval+=1
set /a linePos+=1
if /I %nextNum% GTR 9 set /a "spaceInterval+=1" & set /a linePos+=1
set currLine=!currLine:~%spaceInterval%!
goto FindNext_internal_loop

:NextNumInLine
set nextNum=
for /F %%i IN (%1) DO set /a nextNum=%%i
if "%nextNum%"=="" goto :eof
set /a spaceInterval=0
set val=%~1
:NextNumInLine_loop
if "%val:~0,1%"==" " (
set /a spaceInterval+=1
set val=!val:~1!
goto NextNumInLine_loop
)
goto :eof

这就是您如何称呼它

echo off
setlocal ENABLEDELAYEDEXPANSION
call script.bat input.txt

,其中“input.txt”是包含“程序”输入的文件。

PS 这实际上还没有针对行长度进行优化,我已经花了几个小时才达到这一点,现在我需要睡觉......我明天看看是否可以改进它(目前是“script.bat”) ' 位于 2755 字节)

MS-DOS Batch (yes, you read right!)

I often hear (or read) people say batch isn't very powerful and you can't do much with them, well to them I say, behold, the power of BATCH!

The actual script (script.bat):

set file=%~1
call :FindNextNum 1

for /F "tokens=2 delims=:" %%i IN ('find /c /V "" "%file%"') DO set /a totalLines=%%i

set maxLen=0
for /F "delims=" %%i IN (%file%) DO (
 call :CountChars "%%i"
 if /i !charCount! gtr !maxLen! set maxLen=!charCount!
)

for /L %%i IN (0,1,%totalLines%) DO set "final_%%i=" & for /L %%j IN (0,1,%maxLen%) DO set "final_%%i=!final_%%i! "

:MainLoop
set currLineNum=%lineNum%
set currCol=%linePos%
set currNum=%nextNum%

set /a targetNum=%currNum%+1
call :FindNextNum %targetNum%
if "%nextNum%"=="" goto MainEnd

REM echo %currNum% -^> %nextNum%
if /I %currLineNum% lss %lineNum% (
call :DrawLine %currCol% %currLineNum% %linePos% %lineNum%
) else (
call :DrawLine %linePos% %lineNum% %currCol% %currLineNum%
)

goto MainLoop

:MainEnd
for /L %%i IN (0,1,%totalLines%) DO echo.!final_%%i!
goto:eof


:DrawLine

if /I %2 equ %4 goto:DrawHoriz
set "char=" & set "pos=%1" & set "inc=0"
if /I %1 LSS %3 set "char=\" & set "pos=%1" & set "inc=1"
if /I %1 GTR %3 set "char=/" & set "pos=%1" & set "inc=-1"
for /L %%i IN (%2,1,%4) DO call :DrawChar %%i !pos! %char% & set /a "pos+=%inc%"
goto:DrawEnds

:DrawHoriz
set "start=%1+1" & set "end=%3"
if /I %start% gtr %end% set "start=%3+1" & set "end=%1"
set /a lineEnd=%end%+1
set lineEnd=!final_%2:~%lineEnd%!
for /L %%i IN (%start%,1,%end%) DO set final_%2=!final_%2:~0,%%i!-
set final_%2=!final_%2!!lineEnd!

:DrawEnds
call :DrawChar %2 %1 +
call :DrawChar %4 %3 +
goto:eof

:DrawChar 
set /a skip2=%2+1
if "%3"=="" (
set final_%1=!final_%1:~0,%2!^|!final_%1:~%skip2%!
) else (
set final_%1=!final_%1:~0,%2!%3!final_%1:~%skip2%!
)
goto:eof


:CountChars
set charCount=0
set val=%~1
:CountChars_loop
if not "%val:~1%"=="" (
set /a charCount+=1
set val=!val:~1!
goto CountChars_loop
)
goto:eof



:FindNextNum
for /F "delims=" %%i IN ('type "%file%" ^| find /V /N ""') DO (
for /F "tokens=1,2 delims=[]" %%j IN ("%%i") DO (
    set /a lineNum=%%j-1
    call :FindNext_internal "%%k" %1

    if /I !nextNum! equ %1 goto :eof
)
)

goto:eof

:FindNext_internal
set currLine=%~1
set linePos=0
:FindNext_internal_loop
call :NextNumInLine "%currLine%"
set /a linePos+=%spaceInterval%
if "%nextNum%"=="" goto :EOF
if /I %nextNum% equ %2 goto :EOF
set /a spaceInterval+=1
set /a linePos+=1
if /I %nextNum% GTR 9 set /a "spaceInterval+=1" & set /a linePos+=1
set currLine=!currLine:~%spaceInterval%!
goto FindNext_internal_loop

:NextNumInLine
set nextNum=
for /F %%i IN (%1) DO set /a nextNum=%%i
if "%nextNum%"=="" goto :eof
set /a spaceInterval=0
set val=%~1
:NextNumInLine_loop
if "%val:~0,1%"==" " (
set /a spaceInterval+=1
set val=!val:~1!
goto NextNumInLine_loop
)
goto :eof

And this is how you call it

echo off
setlocal ENABLEDELAYEDEXPANSION
call script.bat input.txt

where "input.txt" is a file that contains the input for the "program".

P.S. This isn't actually optimized for line length yet, I've already spent a couple of hours getting to this point and now I need to sleep... I'll see if I can improve it tomorrow (currently 'script.bat' sits at 2755 bytes)

夏天碎花小短裙 2024-09-02 17:55:13

Rebmu:218 个字符

Ma L{-|\/}Qb|[sg?SBaB]Da| [feSm[TfiSrj[spAsp]iT[++Tbr]]t]Xa|[i?A]Ya|[i?FImHDa]Ca|[skPCmSCaBKfsA]wh[Jd++N][roG[xJyJ]]Bf+ GwhB[JcB Ff+GiF[KcF HqXkXj VqYkYju[chCbPClEZv1[ezH2[eeHv3 4]]e?A+bRE[hV]f]]chJeFIlSCj{+}{+ }Jk Bf]wM

我越来越漂亮了擅长以猪拉丁语形式阅读和编辑它。 (虽然我确实使用换行符!):)

但这就是当不区分大小写的“mushing”技巧被煮掉并且人们习惯了它时,解释器如何转换方言。我会添加一些评论。 (提示:fi是find,fe是foreach,sp是空格字符,i?是索引,hd是头,ch是变化,sk是跳过,pc是挑选,bk 是中断,i 是 if,e 是任一,ee 是相等,令人作呕)

; copy program argument into variable (m)atrix
m: a

; string containing the (l)etters used for walls
l: {-|\/} 

; q is a "b|function" (function that takes two parameters, a and b)
; it gives you the sign of subtracting b from a (+1, -1, or 0)
q: b| [sg? sb a b]

; d finds you the iterator position of the first digit of a two digit
; number in the matrix
d: a| [fe s m [t: fi s rj [sp a sp] i t [++ t br]] t]

; given an iterator position, this tells you the x coordinate of the cell
x: a| [i? a]

; given an iterator position, this tells you the y coordinate of the cell
y: a| [i? fi m hd a]

; pass in a coordinate pair to c and it will give you the iterator position
; of that cell
c: a| [sk pc m sc a bk fr a]

; n defaults to 1 in Rebmu.  we loop through all the numbers up front and
; gather their coordinate pairs into a list called g
wh [j: d ++ n] [ro g [x j y j]]

; b is the (b)eginning coordinate pair for our stroke. f+ returns the
; element at G's current position and advances G (f+ = "first+")
; advance g's iteration position
b: f+ g
wh b [
    ; j is the iterator position of the beginning stroke
    j: c b 

    ; f is the (f)inishing coordinate pair for our stroke
    f: f+ g

    ; if there is a finishing pair, we need to draw a line 
    i f [
        ; k is the iterator position of the end of the stroke
        k: c f

        ; the (h)orizontal and (v)ertical offsets we'll step by (-1,0,1)
        h: q x k x j 
        v: q y k y j 

        u [
            ; change the character at iterator location for b (now our
            ; current location) based on an index into the letters list
            ; that we figure out based on whether v is zero, h is zero,
            ; v equals h, or v doesn't equal h.
            ch c b pc l ez v 1 [ez h 2 [ee h v 3 4]]

            ; if we update the coordinate pair by the offset and it 
            ; equals finish, then we're done with the stroke
            e? a+ b re [h v] f
        ]
    ] 

    ; whether we overwrite the number with a + or a plus and space
    ; depends on whether we detect one of our wall "letters" already
    ; one step to the right of the iterator position
    ch j e fi l sc j {+} {+ }

    ; update from finish pair to be new begin pair for next loop iteration
    j: k
    b: f
] 

; write out m
w m

两者语言和示例是新的并且处于实验阶段。例如,在我对其进行更改以帮助完成此示例之前,ad 无法用于将向量和矩阵相加。但我认为这正是专门为代码高尔夫设计的语言必须具备的东西。这是“语言”和“图书馆”之间的微妙界限。

带注释的最新源代码可在 GitHub 上获取

Rebmu: 218 chars

Ma L{-|\/}Qb|[sg?SBaB]Da|[feSm[TfiSrj[spAsp]iT[++Tbr]]t]Xa|[i?A]Ya|[i?FImHDa]Ca|[skPCmSCaBKfsA]wh[Jd++N][roG[xJyJ]]Bf+GwhB[JcB Ff+GiF[KcF HqXkXj VqYkYju[chCbPClEZv1[ezH2[eeHv3 4]]e?A+bRE[hV]f]]chJeFIlSCj{+}{+ }Jk Bf]wM

I'm getting pretty good at reading and editing it natively in its pig-latin form. (Though I do use line breaks!!) :)

But here's how the dialect is transformed by the interpreter when the case-insensitive "mushing" trick is boiled away, and one gets accustomed to it. I'll add some comments. (Tips: fi is find, fe is foreach, sp is a space character, i? is index, hd is head, ch is change, sk is skip, pc is pick, bk is break, i is if, e is either, ee is either equal, ad nauseum)

; copy program argument into variable (m)atrix
m: a

; string containing the (l)etters used for walls
l: {-|\/} 

; q is a "b|function" (function that takes two parameters, a and b)
; it gives you the sign of subtracting b from a (+1, -1, or 0)
q: b| [sg? sb a b]

; d finds you the iterator position of the first digit of a two digit
; number in the matrix
d: a| [fe s m [t: fi s rj [sp a sp] i t [++ t br]] t]

; given an iterator position, this tells you the x coordinate of the cell
x: a| [i? a]

; given an iterator position, this tells you the y coordinate of the cell
y: a| [i? fi m hd a]

; pass in a coordinate pair to c and it will give you the iterator position
; of that cell
c: a| [sk pc m sc a bk fr a]

; n defaults to 1 in Rebmu.  we loop through all the numbers up front and
; gather their coordinate pairs into a list called g
wh [j: d ++ n] [ro g [x j y j]]

; b is the (b)eginning coordinate pair for our stroke. f+ returns the
; element at G's current position and advances G (f+ = "first+")
; advance g's iteration position
b: f+ g
wh b [
    ; j is the iterator position of the beginning stroke
    j: c b 

    ; f is the (f)inishing coordinate pair for our stroke
    f: f+ g

    ; if there is a finishing pair, we need to draw a line 
    i f [
        ; k is the iterator position of the end of the stroke
        k: c f

        ; the (h)orizontal and (v)ertical offsets we'll step by (-1,0,1)
        h: q x k x j 
        v: q y k y j 

        u [
            ; change the character at iterator location for b (now our
            ; current location) based on an index into the letters list
            ; that we figure out based on whether v is zero, h is zero,
            ; v equals h, or v doesn't equal h.
            ch c b pc l ez v 1 [ez h 2 [ee h v 3 4]]

            ; if we update the coordinate pair by the offset and it 
            ; equals finish, then we're done with the stroke
            e? a+ b re [h v] f
        ]
    ] 

    ; whether we overwrite the number with a + or a plus and space
    ; depends on whether we detect one of our wall "letters" already
    ; one step to the right of the iterator position
    ch j e fi l sc j {+} {+ }

    ; update from finish pair to be new begin pair for next loop iteration
    j: k
    b: f
] 

; write out m
w m

Both the language and sample are new and in an experimental stage. For instance, ad couldn't be used to add together vectors and matrices before I changed it to help with this sample. But I think that's just the sort of thing that a language designed specifically for code golf has to have anyway. It's a subtle line between "language" and "library".

Latest source with comments available on GitHub

巾帼英雄 2024-09-02 17:55:13

Haskell,424 个字符

当前字符数:424 430 451 466 511 515 <德尔>516 <德尔>518 525 532 541 545 550 556 569 571 577 582 586< /del> 592

import List
x%c=[(i,c)|i<-x]
l k p q|p>q=l k q p|True=head[[p,p+j..q]%c|m<-zip[k-1,k,k+1,1]"/|\\-",let (j,c)=m,mod(q-p)j==0]
w=map snd
q(k,m,x)z=w$sort$nubBy((==)&fst)$x%'+'++(concat$zipWith(l k)x$tail x)++z%'\n'++[1..m]%' '
r(z,m,x)=q(last z,m-1,w$sort x)z
u[(m,_)]n x=(-m::Int,n):x;u _ _ x=x
t(z,n,x)s|s=="\n"=(n:z,n+1,x)|True=(z,n+length s,u(reads s)n x)
y&x=(.x).y.x
main=interact$r.foldl t([],1,[]).groupBy((&&)&(>' '))

这个版本从下面的原始 Haskell 条目中汲取了很多灵感,但做出了一些重大更改。最重要的是,它用单个索引而不是一对坐标表示图像位置。

有一些更改:

  1. 输入现在必须将所有行填充到相同的长度(规则允许)。
  2. 不再需要任何语言扩展

原始版本:

(需要< code>-XTupleSections,可能还有 -XNoMonomorphismRestriction

import List
b=length
f=map
g=reverse
a(x,y)" "=(x,y+1)
a(x,y)z=([y,read z]:x,y+b z)
x%y=[min x y+1..max x y-1]
j([x,y],[w,z])|y==z=f(,'-')$f(y,)$x%w|x==w=f(,'|')$f(,x)$y%z|(y<z)==(x<w)=f(,'\\')$zip(y%z)$x%w|True=f(,'/')$zip(y%z)$g$x%w
k 0='\n'
k _=' '
y&x=(.x).y.x
y?x=f y.sort.x.concat
r z=snd?(nubBy((==)&fst).g)$[((y,x),k x)|x<-[0..maximum$f b d],y<-[1..b d]]:[((y,x),'+')|[x,y]<-e]:(f j$zip e$tail e)where d=f(groupBy$(&&)&(>' '))$lines z;e=tail?f g$zipWith(f.(:))[1..]$f(fst.foldl a([],1))d
main=interact r

解释:

(1) d=...:将输入拆分为空格和数字,例如

   z = " 6  5\n\n1       2\n\n    4   3\n\n 7"
=> d = [[" ","6"," "," ","5"],[],["1"," "," "," "," "," "," "," ","2"],[],[" "," "," "," ","4"," "," "," ","3"],[],[" ","7"]]

(2) e=...:将 d 转换为每个数字的 (y, x) 坐标列表。

   e = [[1,3],[9,3],[9,5],[5,5],[5,1],[2,1],[2,7]]
--- //  1     2     3     4     5     6     7

(3)

  • [((y,x),kx)|...] 是一个空板。 (k 返回空格或 \n,具体取决于 x 坐标。)
  • [((y,x),'+'))|.. .] 是数字处的加号。
  • (fj$zip e$tail e) 是连接数字的线。 (j 将一对坐标映射到代表一条线的(坐标、字符)列表中。)

这 3 个组件被连接并过滤以形成实际的输出。请注意,顺序很重要,因此 nubBy(...).g 只能将最后一个字符保留在同一位置。

Haskell, 424 chars

Current char count: 424 430 451 466 511 515 516 518 525 532 541 545 550 556 569 571 577 582 586 592.

import List
x%c=[(i,c)|i<-x]
l k p q|p>q=l k q p|True=head[[p,p+j..q]%c|m<-zip[k-1,k,k+1,1]"/|\\-",let (j,c)=m,mod(q-p)j==0]
w=map snd
q(k,m,x)z=w$sort$nubBy((==)&fst)$x%'+'++(concat$zipWith(l k)x$tail x)++z%'\n'++[1..m]%' '
r(z,m,x)=q(last z,m-1,w$sort x)z
u[(m,_)]n x=(-m::Int,n):x;u _ _ x=x
t(z,n,x)s|s=="\n"=(n:z,n+1,x)|True=(z,n+length s,u(reads s)n x)
y&x=(.x).y.x
main=interact$r.foldl t([],1,[]).groupBy((&&)&(>' '))

This version takes a lot of inspiration from the original Haskell entry below, but makes some significant changes. Most importantly, it represents image locations with a single index, not a pair of coordinates.

There are some changes:

  1. The input must now have all lines padded to the same length (allowed by the rules.)
  2. No longer needs either language extension

Original version:

(Needs -XTupleSections, and maybe -XNoMonomorphismRestriction)

import List
b=length
f=map
g=reverse
a(x,y)" "=(x,y+1)
a(x,y)z=([y,read z]:x,y+b z)
x%y=[min x y+1..max x y-1]
j([x,y],[w,z])|y==z=f(,'-')$f(y,)$x%w|x==w=f(,'|')$f(,x)$y%z|(y<z)==(x<w)=f(,'\\')$zip(y%z)$x%w|True=f(,'/')$zip(y%z)$g$x%w
k 0='\n'
k _=' '
y&x=(.x).y.x
y?x=f y.sort.x.concat
r z=snd?(nubBy((==)&fst).g)$[((y,x),k x)|x<-[0..maximum$f b d],y<-[1..b d]]:[((y,x),'+')|[x,y]<-e]:(f j$zip e$tail e)where d=f(groupBy$(&&)&(>' '))$lines z;e=tail?f g$zipWith(f.(:))[1..]$f(fst.foldl a([],1))d
main=interact r

Explanation:

(1) d=...: Splits the input into spaces and numbers, e.g.

   z = " 6  5\n\n1       2\n\n    4   3\n\n 7"
=> d = [[" ","6"," "," ","5"],[],["1"," "," "," "," "," "," "," ","2"],[],[" "," "," "," ","4"," "," "," ","3"],[],[" ","7"]]

(2) e=...: Converts d into a list of (y, x) coordinates for each number.

   e = [[1,3],[9,3],[9,5],[5,5],[5,1],[2,1],[2,7]]
--- //  1     2     3     4     5     6     7

(3)

  • [((y,x),k x)|...] is an empty board. (k returns a space or a \n depending on the x-coordinate.)
  • [((y,x),'+'))|...] are the plus signs at the numbers.
  • (f j$zip e$tail e) are the lines connecting the numbers. (j maps a pair of coordinates into a list of (coordinate, character) which represents a line.)

These 3 components are concatenated and filtered to form the actual output. Note that the order is important, so that nubBy(...).g can only keep the last character in the same location.

芯好空 2024-09-02 17:55:13

AWK - 296 317 321 324 334 340

还不是获奖者,但我对我的努力感到满意(用于显示的换行符)。这个新版本使用 VT-100 转义序列。 '^['只是一个字符,Escape!!!在此版本中,剪切和粘贴不起作用,因为序列“^[”必须替换为真正的 ESC 字符。为了使论坛友好,可以将 ESC 指定为“\0x1b”,但它占用太多空间...

BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR;
m=m>k?m:k}}}END{printf"^[[2J[%d;%dH+",Y=y[i=1],X=x[1];while(a=x[++i])
{a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;
for(r=a?a*A:b*B;--r;){printf"^[[%d;%dH%c",Y+=B,X+=A,t}
printf"^[[%d;%dH+",Y+=B,X+=A}}

旧的标准版本

BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR;
m=m>k?m:k}}}END{q[X=x[1],Y=y[i=1]]=43;while(a=x[++i]){a-=X;b=y[i]-Y;
t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;for(r=a?a*A:b*B;--r;
q[X+=A,Y+=B]=t);q[X+=A,Y+=B]=43}for(j=0;++j<NR;){for(i=0;i<m;){t=q[i++,j];
printf"%c",t?t:32}print}}

现在稍微解释一下

# This will break the input in fields separated by exactly 1 space,
# i.e. the fields will be null or a number.

BEGIN{FS="[ ]"}

# For each line we loop over all fields, if the field is not null 
# it is a number, hence store it.
# Also account for the fact the numbers use space.
# Also, find the maximum width of the line.

{
    for(j=i=0;i<NF;j+=length(g)){
        if(g=$++i){
            k=j+i;x[g]=k;y[g]=NR;m=m>k?m:k
        }
    }
}

# Once we have all the data, let start cooking.

END{
    # First, create a matrix with the drawing.
    # first point is a +

    q[X=x[1],Y=y[i=1]]=43;

    # loop over all points

    while(a=x[++i]){

        # Check next point and select character
        # If a == 0 -> -
        # If b == 0 -> |
        # If a and b have same sign -> \ else /

        a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124;

        # there is no sgn() function
        A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;

        # Draw the line between the points

        for(k=0;++k<(a?a*A:b*B);){
            q[X+=A,Y+=B]=t
        }

        # store + and move to next point

        q[X+=A,Y+=B]=43
    }
    # Now output all lines. If value in point x,y is 0, emit space
    for(j=0;++j<NR;){
        for(i=0;i<m;){
            t=q[i++,j];printf("%c",t?t:32)
        }
        print
    }
}

AWK - 296 317 321 324 334 340

Not a prize winner (yet), but I am pleased with the effort (line breaks for display). This new version uses VT-100 escape sequences. The '^[' is just one character, Escape!!! Cut and paste will not work with this version, since the sequence "^[" has to be replaced with the real ESC character. To make it forum friendly, ESC could be specified as "\0x1b", but it takes too much space...

BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR;
m=m>k?m:k}}}END{printf"^[[2J[%d;%dH+",Y=y[i=1],X=x[1];while(a=x[++i])
{a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;
for(r=a?a*A:b*B;--r;){printf"^[[%d;%dH%c",Y+=B,X+=A,t}
printf"^[[%d;%dH+",Y+=B,X+=A}}

The older standard version

BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR;
m=m>k?m:k}}}END{q[X=x[1],Y=y[i=1]]=43;while(a=x[++i]){a-=X;b=y[i]-Y;
t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;for(r=a?a*A:b*B;--r;
q[X+=A,Y+=B]=t);q[X+=A,Y+=B]=43}for(j=0;++j<NR;){for(i=0;i<m;){t=q[i++,j];
printf"%c",t?t:32}print}}

Now a little explanation

# This will break the input in fields separated by exactly 1 space,
# i.e. the fields will be null or a number.

BEGIN{FS="[ ]"}

# For each line we loop over all fields, if the field is not null 
# it is a number, hence store it.
# Also account for the fact the numbers use space.
# Also, find the maximum width of the line.

{
    for(j=i=0;i<NF;j+=length(g)){
        if(g=$++i){
            k=j+i;x[g]=k;y[g]=NR;m=m>k?m:k
        }
    }
}

# Once we have all the data, let start cooking.

END{
    # First, create a matrix with the drawing.
    # first point is a +

    q[X=x[1],Y=y[i=1]]=43;

    # loop over all points

    while(a=x[++i]){

        # Check next point and select character
        # If a == 0 -> -
        # If b == 0 -> |
        # If a and b have same sign -> \ else /

        a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124;

        # there is no sgn() function
        A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;

        # Draw the line between the points

        for(k=0;++k<(a?a*A:b*B);){
            q[X+=A,Y+=B]=t
        }

        # store + and move to next point

        q[X+=A,Y+=B]=43
    }
    # Now output all lines. If value in point x,y is 0, emit space
    for(j=0;++j<NR;){
        for(i=0;i<m;){
            t=q[i++,j];printf("%c",t?t:32)
        }
        print
    }
}
谈场末日恋爱 2024-09-02 17:55:13

C, 386

402 C 中的 386 个字符。第一个后面的换行符仅用于可读性。

#include <stdio.h>
int x[101],y[101],c=1,r,w,h,b,i,j,k,m,n;
int main(){
while((b=getchar())-EOF)
b-' '?b-'\n'?ungetc(b,stdin),scanf("%d",&b),x[b]=c++,y[b]=h,c+=b>9:(w=c>w?c:w,++h,c=1):++c;
for(r=0;r<h&&putchar('\n');++r)
for(c=0;c<w;++c){
for(b=' ',i=2,m=x[1]-c,n=y[1]-r;j=m,k=n,m=x[i]-c,n=y[i]-r,x[i++];)
b=j|k&&m|n?j*m>0|k|n?k*n<0?(j-k|m-n?j+k|m+n?j|m?b:'|':'/':'\\'):b:'-':'+';
putchar(b);
}
}

C, 386

402 386 character in C. Newlines after the first are only for readability.

#include <stdio.h>
int x[101],y[101],c=1,r,w,h,b,i,j,k,m,n;
int main(){
while((b=getchar())-EOF)
b-' '?b-'\n'?ungetc(b,stdin),scanf("%d",&b),x[b]=c++,y[b]=h,c+=b>9:(w=c>w?c:w,++h,c=1):++c;
for(r=0;r<h&&putchar('\n');++r)
for(c=0;c<w;++c){
for(b=' ',i=2,m=x[1]-c,n=y[1]-r;j=m,k=n,m=x[i]-c,n=y[i]-r,x[i++];)
b=j|k&&m|n?j*m>0|k|n?k*n<0?(j-k|m-n?j+k|m+n?j|m?b:'|':'/':'\\'):b:'-':'+';
putchar(b);
}
}
身边 2024-09-02 17:55:13

英特尔汇编器

汇编大小:506 字节

来源:2252 字节(嘿,这不是一个小问题)

汇编:使用 A86
运行:使用 WinXP DOS 框进行测试。调用jtd.com <输入>输出

    mov ax,3
    int 10h
    mov ax,0b800h
    mov es,ax
    mov ah,0bh
    int 21h
    mov bx,255
    cmp al,bl
    mov dh,bh
    mov si,offset a12
    push offset a24
    je a1
    mov si,offset a14
a1: inc bl
a2: mov dl,255
    call si
    cmp al,10
    jb a4
a3: cmp al,10-48
    jne a1
    inc bh
    mov bl,dh
    jmp a2
a4: mov dl,al
    call si
    cmp al,10
    jae a5
    mov ah,dl
    aad
    mov dl,al
a5: mov di,dx
    mov ch,al
    shl di,2
    mov [di+a32],bx
    cmp bl,[offset a30]
    jb a6
    mov [offset a30],bl
a6: cmp bh,[offset a31]
    jb a7
    mov [offset a31],bh
a7: push offset a19
    mov al,80
    mul bh
    add al,bl
    adc ah,0
    add ax,ax
    lea di,[di+2+a32]
    mov [di],ax
    add di,2
    cmp di,[a22-3]
    jbe a8
    mov [a22-3],di
    mov [a25-3],di
a8: mov di,ax
    mov al,dl
    aam
    cmp ah,0
    je a10
a9: add ah,48
    mov es:[di],ah
    add di,2
a10:add al,48
    mov es:[di],al
    mov al,ch
    inc bl
    jmp a3
a11:jmp si
a12:mov ah,0bh
    int 21h
    cmp al,255
    jne a15
    mov ah,8
    int 21h
a13:cmp al,13
    je a11
    sub al,48
    ret
a14:mov ah,1
    int 21h
    cmp al,26
    jne a13
    mov si,offset a15
    ret
a15:cmp dl,255
    je a16
    mov al,32
    ret
a16:mov si,offset a32 + 4
    lodsw
    mov cx,ax
    mov dx,ax
    lodsw
    mov di,ax
    mov b es:[di],1
    mov bp,0f000h
    call a26
    add sp,6
    mov bx,[a22-3]
    mov ax,[offset a31]
    inc ax
a17:mov bp,[offset a30]
a18:mov b[bx],32
    inc bx
    dec bp
    jnz a18
    mov w[bx],0a0dh
    add bx,2
    dec ax
    jnz a17
    mov b[bx],'

有趣的功能:自修改代码、动画输出(第二个示例有效,但太大而无法显示)、滥用“ret”来实现循环计数器、确定线条/移动方向的有趣方法。

add w[a30],2 a19:lodsw xchg ax,dx cmp ah,dh lahf mov bl,ah cmp al,dl lahf shr bl,6 shr ah,4 and ah,12 or bl,ah mov bh,0 shl bx,3 a20:mov b es:[di],43 a21:mov al,b[a30] mul ch add al,cl adc ah,0 mov bp,ax mov b[bp+100h],43 a22:add di,[bx + a29] add cl,[bx + a29 + 4] add ch,[bx + a29 + 6] mov b es:[di],1 mov al,[bx + a29 + 2] mov [a21-1],al mov [a22-1],al mov bp,01000h call a26 cmp di,[si] jne a20 mov al,es:[di+2] sub al,48 cmp al,10 jae a23 mov b es:[di+2],0 a23:mov b[a21-1],43 mov b[a22-1],43 mov b es:[di],43 lodsw ret a24:mov al,b[a30] mul ch add al,cl adc ah,0 mov bp,ax mov b[bp+100h],43 a25:mov dx,[a22-3] mov ah,9 int 21h ret a26:pusha a27:mov cx,0ffffh a28:loop a28 dec bp jnz a27 popa ret a29:dw -162,92,-1,-1,-2,45,-1,0,158,47,-1,1,0,0,0,0,-160,124,0,-1 a30:dw 0 a31:dw 0,0,0,160,124,0,1,0,0,0,0,-158,47,1,-1,2,45,1,0,162,92,1,1 a32:

有趣的功能:自修改代码、动画输出(第二个示例有效,但太大而无法显示)、滥用“ret”来实现循环计数器、确定线条/移动方向的有趣方法。

Intel Assembler

Assembled size: 506 bytes

Source: 2252 bytes (hey, it's not a trivial problem this one)

To Assemble: Use A86
To Run: Tested with a WinXP DOS box. Invocation jtd.com < input > output

    mov ax,3
    int 10h
    mov ax,0b800h
    mov es,ax
    mov ah,0bh
    int 21h
    mov bx,255
    cmp al,bl
    mov dh,bh
    mov si,offset a12
    push offset a24
    je a1
    mov si,offset a14
a1: inc bl
a2: mov dl,255
    call si
    cmp al,10
    jb a4
a3: cmp al,10-48
    jne a1
    inc bh
    mov bl,dh
    jmp a2
a4: mov dl,al
    call si
    cmp al,10
    jae a5
    mov ah,dl
    aad
    mov dl,al
a5: mov di,dx
    mov ch,al
    shl di,2
    mov [di+a32],bx
    cmp bl,[offset a30]
    jb a6
    mov [offset a30],bl
a6: cmp bh,[offset a31]
    jb a7
    mov [offset a31],bh
a7: push offset a19
    mov al,80
    mul bh
    add al,bl
    adc ah,0
    add ax,ax
    lea di,[di+2+a32]
    mov [di],ax
    add di,2
    cmp di,[a22-3]
    jbe a8
    mov [a22-3],di
    mov [a25-3],di
a8: mov di,ax
    mov al,dl
    aam
    cmp ah,0
    je a10
a9: add ah,48
    mov es:[di],ah
    add di,2
a10:add al,48
    mov es:[di],al
    mov al,ch
    inc bl
    jmp a3
a11:jmp si
a12:mov ah,0bh
    int 21h
    cmp al,255
    jne a15
    mov ah,8
    int 21h
a13:cmp al,13
    je a11
    sub al,48
    ret
a14:mov ah,1
    int 21h
    cmp al,26
    jne a13
    mov si,offset a15
    ret
a15:cmp dl,255
    je a16
    mov al,32
    ret
a16:mov si,offset a32 + 4
    lodsw
    mov cx,ax
    mov dx,ax
    lodsw
    mov di,ax
    mov b es:[di],1
    mov bp,0f000h
    call a26
    add sp,6
    mov bx,[a22-3]
    mov ax,[offset a31]
    inc ax
a17:mov bp,[offset a30]
a18:mov b[bx],32
    inc bx
    dec bp
    jnz a18
    mov w[bx],0a0dh
    add bx,2
    dec ax
    jnz a17
    mov b[bx],'

Interesting features: self modifying code, animated output (the second example works, but is too big to display), abuse of 'ret' to implement a loop counter, interesting way of determining line/movement direction.

add w[a30],2 a19:lodsw xchg ax,dx cmp ah,dh lahf mov bl,ah cmp al,dl lahf shr bl,6 shr ah,4 and ah,12 or bl,ah mov bh,0 shl bx,3 a20:mov b es:[di],43 a21:mov al,b[a30] mul ch add al,cl adc ah,0 mov bp,ax mov b[bp+100h],43 a22:add di,[bx + a29] add cl,[bx + a29 + 4] add ch,[bx + a29 + 6] mov b es:[di],1 mov al,[bx + a29 + 2] mov [a21-1],al mov [a22-1],al mov bp,01000h call a26 cmp di,[si] jne a20 mov al,es:[di+2] sub al,48 cmp al,10 jae a23 mov b es:[di+2],0 a23:mov b[a21-1],43 mov b[a22-1],43 mov b es:[di],43 lodsw ret a24:mov al,b[a30] mul ch add al,cl adc ah,0 mov bp,ax mov b[bp+100h],43 a25:mov dx,[a22-3] mov ah,9 int 21h ret a26:pusha a27:mov cx,0ffffh a28:loop a28 dec bp jnz a27 popa ret a29:dw -162,92,-1,-1,-2,45,-1,0,158,47,-1,1,0,0,0,0,-160,124,0,-1 a30:dw 0 a31:dw 0,0,0,160,124,0,1,0,0,0,0,-158,47,1,-1,2,45,1,0,162,92,1,1 a32:

Interesting features: self modifying code, animated output (the second example works, but is too big to display), abuse of 'ret' to implement a loop counter, interesting way of determining line/movement direction.

软糯酥胸 2024-09-02 17:55:13

F#,725 个字符

open System
let mutable h,s,l=0,Set.empty,Console.ReadLine()
while l<>null do
 l.Split([|' '|],StringSplitOptions.RemoveEmptyEntries)
 |>Seq.iter(fun t->s<-s.Add(int t,h,(" "+l+" ").IndexOf(" "+t+" ")))
 h<-h+1;l<-Console.ReadLine()
let w=Seq.map(fun(k,h,x)->x)s|>Seq.max
let o=Array2D.create h (w+1)' '
Seq.sort s|>Seq.pairwise|>Seq.iter(fun((_,b,a),(_,y,x))->
let a,b,x,y=if b>y then x,y,a,b else a,b,x,y
o.[b,a]<-'+'
o.[y,x]<-'+'
if b=y then for x in(min a x)+1..(max a x)-1 do o.[y,x]<-'-'
elif a=x then for h in b+1..y-1 do o.[h,x]<-'|'
elif a<x then for i in 1..y-b-1 do o.[b+i,a+i]<-'\\'
else for i in 1..y-b-1 do o.[b+i,a-i]<-'/')
for h in 0..h-1 do
 for x in 0..w do printf"%c"o.[h,x]
 printfn""

图例:

h = height
s = set
l = curLine
w = (one less than) width
o = output array of chars

第 1-6 行:我保留一组 (number, lineNum, xCoord) 元组;当我阅读每一行输入时,我找到所有数字并将它们添加到集合中。

第 7-8 行:然后我创建一个输出字符数组,并初始化为所有空格。

第 9 行:对集合进行排序(按“数字”),然后取每个相邻对并...

第 10-16 行:...排序,使 (a,b) 是两个点中的“最高”点,并且 (x, y) 是另一个。放置“+”号,然后如果水平,则绘制它,否则如果垂直,则绘制它,否则绘制正确的对角线。如果输入不是“有效”,那么谁知道会发生什么(在我将其高尔夫化之前,这段代码就充满了“断言”)。

第 17-19 行:打印结果

F#, 725 chars

open System
let mutable h,s,l=0,Set.empty,Console.ReadLine()
while l<>null do
 l.Split([|' '|],StringSplitOptions.RemoveEmptyEntries)
 |>Seq.iter(fun t->s<-s.Add(int t,h,(" "+l+" ").IndexOf(" "+t+" ")))
 h<-h+1;l<-Console.ReadLine()
let w=Seq.map(fun(k,h,x)->x)s|>Seq.max
let o=Array2D.create h (w+1)' '
Seq.sort s|>Seq.pairwise|>Seq.iter(fun((_,b,a),(_,y,x))->
let a,b,x,y=if b>y then x,y,a,b else a,b,x,y
o.[b,a]<-'+'
o.[y,x]<-'+'
if b=y then for x in(min a x)+1..(max a x)-1 do o.[y,x]<-'-'
elif a=x then for h in b+1..y-1 do o.[h,x]<-'|'
elif a<x then for i in 1..y-b-1 do o.[b+i,a+i]<-'\\'
else for i in 1..y-b-1 do o.[b+i,a-i]<-'/')
for h in 0..h-1 do
 for x in 0..w do printf"%c"o.[h,x]
 printfn""

Legend:

h = height
s = set
l = curLine
w = (one less than) width
o = output array of chars

Lines 1-6: I keep a set of (number, lineNum, xCoord) tuples; as I read in each line of input I find all the numbers and add them to the set.

Line 7-8: Then I create an array of output chars, initialized to all spaces.

Line 9: Sort the set (by 'number'), then take each adjacent pair and ...

Lines 10-16: ... sort so (a,b) is the 'highest' of the two points and (x,y) is the other. Put the '+' signs, and then if horizontal, draw that, else if vertical, draw that, else draw the correct diagonal. If the input is not 'valid', then who knows what happens (this code was littered with 'asserts' before I golf-ized it).

Lines 17-19: Print the result

泪之魂 2024-09-02 17:55:13

Powershell,328 304 个字符

$i=$l=0;$k=@{}
$s=@($input|%{[regex]::matches($_,"\d+")|%{$k[1*$_.Value]=@{y=$l
x=$_.Index}};$l++;""})
while($a=$k[++$i]){
if($i-eq1){$x=$a.x;$y=$a.y}
do{$d=$a.x.CompareTo($x);$e=$a.y.CompareTo($y)
$s[$y]=$s[($y+=$e)].PadRight($x+1).Remove($x,1).Insert(($x+=$d),
"\-/|+|/-\"[4+$d*3+$e])}while($d-or$e)}$s

,这是一个带有注释的漂亮打印版本:

# Usage: gc testfile.txt | dots.ps1

$l=$i=0            # line, dot index (used below)
$k=@{}             # hashtable that maps dot index to coordinates  

# Apply regular expression to each line of the input
$s=@( $input | foreach{     
        [regex]::matches($_,"\d+") | foreach{
            # Store each match in the hashtable
            $k[ 1*$_.Value ] = @{ y = $l; x = $_.Index }
        }
        $l++; # Next line
        ""    # For each line return an empty string.
              # The strings are added to the array $s which
              # is used to produce the final output
    }
)

# Connect the dots!
while( $a = $k[ ++$i ] )
{
    if( $i -eq 1 )  # First dot?
    {
        # Current position is ($x, $y)
        $x = $a.x;
        $y = $a.y
    }

    do
    {
        $d = $a.x.CompareTo( $x )           # sign( $a.x - $x )
        $e = $a.y.CompareTo( $y )           # sign( $a.y - $y )
        $c = '\-/|+|/-\'[ 4 + $d * 3 + $e ] # character            '

        # Move
        $x += $d                            
        $y += $e

        # "Replace" the charcter at the current position
        # PadRight() ensures the string is long enough          
        $s[ $y ]=$s[ $y ].PadRight( $x+1 ).Remove( $x, 1 ).Insert( $x, $c )
    } while( $d -or $e ) # Until the next dot is reached
}

# Print the resulting string array
$s

Powershell, 328 304 characters

$i=$l=0;$k=@{}
$s=@($input|%{[regex]::matches($_,"\d+")|%{$k[1*$_.Value]=@{y=$l
x=$_.Index}};$l++;""})
while($a=$k[++$i]){
if($i-eq1){$x=$a.x;$y=$a.y}
do{$d=$a.x.CompareTo($x);$e=$a.y.CompareTo($y)
$s[$y]=$s[($y+=$e)].PadRight($x+1).Remove($x,1).Insert(($x+=$d),
"\-/|+|/-\"[4+$d*3+$e])}while($d-or$e)}$s

and here's a pretty-printed version with comments:

# Usage: gc testfile.txt | dots.ps1

$l=$i=0            # line, dot index (used below)
$k=@{}             # hashtable that maps dot index to coordinates  

# Apply regular expression to each line of the input
$s=@( $input | foreach{     
        [regex]::matches($_,"\d+") | foreach{
            # Store each match in the hashtable
            $k[ 1*$_.Value ] = @{ y = $l; x = $_.Index }
        }
        $l++; # Next line
        ""    # For each line return an empty string.
              # The strings are added to the array $s which
              # is used to produce the final output
    }
)

# Connect the dots!
while( $a = $k[ ++$i ] )
{
    if( $i -eq 1 )  # First dot?
    {
        # Current position is ($x, $y)
        $x = $a.x;
        $y = $a.y
    }

    do
    {
        $d = $a.x.CompareTo( $x )           # sign( $a.x - $x )
        $e = $a.y.CompareTo( $y )           # sign( $a.y - $y )
        $c = '\-/|+|/-\'[ 4 + $d * 3 + $e ] # character            '

        # Move
        $x += $d                            
        $y += $e

        # "Replace" the charcter at the current position
        # PadRight() ensures the string is long enough          
        $s[ $y ]=$s[ $y ].PadRight( $x+1 ).Remove( $x, 1 ).Insert( $x, $c )
    } while( $d -or $e ) # Until the next dot is reached
}

# Print the resulting string array
$s
梦开始←不甜 2024-09-02 17:55:13

Python - 381

import re
b=list(iter(raw_input,''))
c=sum((zip([i]*999,re.finditer('\\d+',x))for i,x in enumerate(b)),[])
d=sorted((int(m.group()),i,m.start())for i,m in c)
e=[[' ']*max(map(len,b))for x in b]
for(t,u,v),(x,y,z)in zip(d,d[1:]+d[-1:]):
 e[u][v]='+'
 while u!=y or v!=z:i,j=(u<y)-(u>y),(v<z)-(v>z);u+=i;v+=j;e[u][v]=['|','/\\-'[(i==j)+2*(i==0)]][j!=0]
print'\n'.join(map(''.join,e))

Python - 381

import re
b=list(iter(raw_input,''))
c=sum((zip([i]*999,re.finditer('\\d+',x))for i,x in enumerate(b)),[])
d=sorted((int(m.group()),i,m.start())for i,m in c)
e=[[' ']*max(map(len,b))for x in b]
for(t,u,v),(x,y,z)in zip(d,d[1:]+d[-1:]):
 e[u][v]='+'
 while u!=y or v!=z:i,j=(u<y)-(u>y),(v<z)-(v>z);u+=i;v+=j;e[u][v]=['|','/\\-'[(i==j)+2*(i==0)]][j!=0]
print'\n'.join(map(''.join,e))
枕梦 2024-09-02 17:55:13

C#,422 个字符

758 754 641 627 584 546罢工> <罢工>532 <罢工>486 <罢工>457 <罢工>454 <罢工>443 <罢工>440 422 个字符(下次也许我不会这么快提交。)

using A=System.Console;class B{static int C,o,d,e,G,O=1,f,F,u,n;static 
void Main(){var s=A.In.ReadToEnd();A.Clear();while(++u<s.Length){f++;if
(s[u]<32){u++;F++;f= 0;}if(s[u]>32){if(int.Parse(s[u]+""+s[++u])==O){o=
e>f?1:f>e?-1:0;C=d>F?1:F>d?-1:0 ;G=e+o;n=d+C;if(O++>1)while(n!=F||G!=f)
{A.SetCursorPosition(G-=o,n-=C);A.Write( "+/-|\\"[n==d&&G==e?0:n==F&&G
==f?0:C+o==0?1:C==0?2:o==0?3:4]);}e=f;d=F;F=0;f=u=-1 ;}f++;}}A.Read();}}

用法:运行,粘贴(或键入)输入,确保最后一行终止,按 CTRL-Z 或 F6,按 Enter。

格式化但仍然基本无法理解的版本:

using A = System.Console;
class B
{
    // code golf fun!
    static int C, o, d, e, G, O = 1, f, F, u, n;
    static void Main()
    {
        // read the input into a string char by char until EOF
        var s = A.In.ReadToEnd();
      
        A.Clear(); // clear console, ready to draw picture

        // O is the "dot" number we're looking for 
        // f is current column 
        // F is current row
        // loop over the field looking for numbers sequentially 
        // until no more are found
        while (++u < s.Length)
        {
            f++;
            // any char <32 is expected to be a CR/LF 
            // increment the current row and reset the current column
            if (s[u] < 32)
            {
                u++; // skip the other half of the CR/LF pair
                F++; // next row
                f = 0; // column reset
            }
            // any char >32 is expected to be a number
            if (s[u] > 32)
            {
                // parse the current + next char and see if it's 
                // the number we want
                if (int.Parse(s[u] + "" + s[++u]) == O)
                {
                    // set up coordinates, compare X1 with X2 
                    // and Y1 with Y2 to figure out line direction
                    
                    // horizontal direction (same as o=e.CompareTo(f))
                    o = e > f ? 1 : f > e ? - 1 : 0; 

                    // vertical direction (same as C=d.CompareTo(F))
                    C = d > F ? 1 : F > d ? - 1 : 0; 

                    // initial offsets compensate for off-by-one
                    G = e + o;
                    n = d + C;

                    // draw the line (except for the very first dot) 
                    if (O++ > 1)
                        while (n != F || G != f)
                        {
                            // update coords and write desired char 
                            A.SetCursorPosition(G -= o, n -= C);

                            // this lovely line decides which char to 
                            // print, and prints it
                            A.Write(
                               "+/-|\\"[n == d && G == e ? 0 : n == F && G 
                               == f ? 0 : C + o == 0 ? 1 : C == 0 ? 2 : o 
                               == 0 ? 3 : 4]);
                        }

                    // remember end point of this line, to use as start point 
                    // of next line
                    e = f;
                    d = F;

                    // reset current row (F), column (f), field position (u)
                    F = 0;
                    f = u = -1;
                }
           
                // bump current column because we parse 2 chars when we 
                // find a dot                
                f++;                 
            }
        }
        A.Read(); // prevent command prompt from overwriting picture
    }
}

C#, 422 chars

758 754 641 627 584 546 532 486 457 454 443 440 422 chars (next time maybe I won't submit so soon.)

using A=System.Console;class B{static int C,o,d,e,G,O=1,f,F,u,n;static 
void Main(){var s=A.In.ReadToEnd();A.Clear();while(++u<s.Length){f++;if
(s[u]<32){u++;F++;f= 0;}if(s[u]>32){if(int.Parse(s[u]+""+s[++u])==O){o=
e>f?1:f>e?-1:0;C=d>F?1:F>d?-1:0 ;G=e+o;n=d+C;if(O++>1)while(n!=F||G!=f)
{A.SetCursorPosition(G-=o,n-=C);A.Write( "+/-|\\"[n==d&&G==e?0:n==F&&G
==f?0:C+o==0?1:C==0?2:o==0?3:4]);}e=f;d=F;F=0;f=u=-1 ;}f++;}}A.Read();}}

Usage: run, paste (or type) the input, ensure the last line is terminated, press CTRL-Z or F6, press Enter.

Formatted but still basically unintelligable version:

using A = System.Console;
class B
{
    // code golf fun!
    static int C, o, d, e, G, O = 1, f, F, u, n;
    static void Main()
    {
        // read the input into a string char by char until EOF
        var s = A.In.ReadToEnd();
      
        A.Clear(); // clear console, ready to draw picture

        // O is the "dot" number we're looking for 
        // f is current column 
        // F is current row
        // loop over the field looking for numbers sequentially 
        // until no more are found
        while (++u < s.Length)
        {
            f++;
            // any char <32 is expected to be a CR/LF 
            // increment the current row and reset the current column
            if (s[u] < 32)
            {
                u++; // skip the other half of the CR/LF pair
                F++; // next row
                f = 0; // column reset
            }
            // any char >32 is expected to be a number
            if (s[u] > 32)
            {
                // parse the current + next char and see if it's 
                // the number we want
                if (int.Parse(s[u] + "" + s[++u]) == O)
                {
                    // set up coordinates, compare X1 with X2 
                    // and Y1 with Y2 to figure out line direction
                    
                    // horizontal direction (same as o=e.CompareTo(f))
                    o = e > f ? 1 : f > e ? - 1 : 0; 

                    // vertical direction (same as C=d.CompareTo(F))
                    C = d > F ? 1 : F > d ? - 1 : 0; 

                    // initial offsets compensate for off-by-one
                    G = e + o;
                    n = d + C;

                    // draw the line (except for the very first dot) 
                    if (O++ > 1)
                        while (n != F || G != f)
                        {
                            // update coords and write desired char 
                            A.SetCursorPosition(G -= o, n -= C);

                            // this lovely line decides which char to 
                            // print, and prints it
                            A.Write(
                               "+/-|\\"[n == d && G == e ? 0 : n == F && G 
                               == f ? 0 : C + o == 0 ? 1 : C == 0 ? 2 : o 
                               == 0 ? 3 : 4]);
                        }

                    // remember end point of this line, to use as start point 
                    // of next line
                    e = f;
                    d = F;

                    // reset current row (F), column (f), field position (u)
                    F = 0;
                    f = u = -1;
                }
           
                // bump current column because we parse 2 chars when we 
                // find a dot                
                f++;                 
            }
        }
        A.Read(); // prevent command prompt from overwriting picture
    }
}
堇色安年 2024-09-02 17:55:13

开始吧!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int sign(int x) {
    if (x < 0)
        return -1;
    if (x > 0)
        return +1;
    return 0;
}

#define MAX_ROWS 100
#define MAX_COLS 100
#define MAX_DIGITS 100

int main(void)
{
    // Read in the digits
    int number[MAX_DIGITS][2];
    int rows = 0;
    int cols = 0;
    char row[MAX_COLS];
    int maxvalue = 0;
    int i, j, value, x;
    for (i = 0; i < MAX_ROWS; i++) {
        if (row != fgets(row, MAX_COLS, stdin))
            break;
        value = 0;
        for (j=0; row[j] != 0; j++) {
            if (row[j] >= '0' && row[j] <= '9') {
                x = j;
                value = 0;
                do {
                    value = 10*value + (row[j]-'0');
                    j++;
                } while (row[j] >= '0' && row[j] <= '9');
                number[value][0] = i;
                number[value][1] = x;
                if (maxvalue < value) maxvalue = value;
                if (rows < i+1) rows = i+1;
                if (cols < x+1) cols = x+1;
            }
        }
    }

    // Create an empty field
    char field[rows][cols];
    memset(field, ' ', rows*cols);

    char lines[] = "\\|/-+-/|\\";
    int dr,dc;
    // Draw the numbers and lines
    field[number[1][0]][number[1][1]] = '+';
    for (i = 2; i <= maxvalue; ++i) {
        int r = number[i-1][0];
        int c = number[i-1][1];
        int rt = number[i][0];
        int ct = number[i][1];
        dr = sign(rt-r);
        dc = sign(ct-c);
        char line = lines[(dr+1)*3+dc+1];
        while (r != rt || c != ct) {
            r += dr;
            c += dc;
            field[r][c] = line;
        }
        field[r][c] = '+';
    }

    for (i = 0; i < rows; ++i) {
        for (j = 0; j < cols; ++j)
            putchar(field[i][j]);
        putchar('\n');
    }

    return 0;
}

Here goes!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int sign(int x) {
    if (x < 0)
        return -1;
    if (x > 0)
        return +1;
    return 0;
}

#define MAX_ROWS 100
#define MAX_COLS 100
#define MAX_DIGITS 100

int main(void)
{
    // Read in the digits
    int number[MAX_DIGITS][2];
    int rows = 0;
    int cols = 0;
    char row[MAX_COLS];
    int maxvalue = 0;
    int i, j, value, x;
    for (i = 0; i < MAX_ROWS; i++) {
        if (row != fgets(row, MAX_COLS, stdin))
            break;
        value = 0;
        for (j=0; row[j] != 0; j++) {
            if (row[j] >= '0' && row[j] <= '9') {
                x = j;
                value = 0;
                do {
                    value = 10*value + (row[j]-'0');
                    j++;
                } while (row[j] >= '0' && row[j] <= '9');
                number[value][0] = i;
                number[value][1] = x;
                if (maxvalue < value) maxvalue = value;
                if (rows < i+1) rows = i+1;
                if (cols < x+1) cols = x+1;
            }
        }
    }

    // Create an empty field
    char field[rows][cols];
    memset(field, ' ', rows*cols);

    char lines[] = "\\|/-+-/|\\";
    int dr,dc;
    // Draw the numbers and lines
    field[number[1][0]][number[1][1]] = '+';
    for (i = 2; i <= maxvalue; ++i) {
        int r = number[i-1][0];
        int c = number[i-1][1];
        int rt = number[i][0];
        int ct = number[i][1];
        dr = sign(rt-r);
        dc = sign(ct-c);
        char line = lines[(dr+1)*3+dc+1];
        while (r != rt || c != ct) {
            r += dr;
            c += dc;
            field[r][c] = line;
        }
        field[r][c] = '+';
    }

    for (i = 0; i < rows; ++i) {
        for (j = 0; j < cols; ++j)
            putchar(field[i][j]);
        putchar('\n');
    }

    return 0;
}
若沐 2024-09-02 17:55:13

C#,638 个字符

using System;
using System.Linq;
using System.Text.RegularExpressions;

class C
{
    static void Main()
    {
        int i=0,j;
        var p = Console.In.ReadToEnd()
            .Split('\n')
            .SelectMany(
                r =>
                {
                    i++; j =0;
                    return Regex.Matches(r, "\\s+(\\d+)").Cast<Match>()
                    .Select(m => { j += m.Length; return new { X = j, Y = i-1, N = int.Parse(m.Groups[1].Value) }; });
                }
        ).OrderBy(a=>a.N).ToList();

        var W = p.Max(a => a.X)+1;
        var k = new char[W*i+W];
        i = 0;
        while (i < p.Count)
        {
            var b = p[i > 0 ? i - 1 : 0]; var a = p[i];
            int h = a.Y - b.Y, w = a.X - b.X;
            var s = "|-/\\"[h == 0 ? 1 : w == 0 ? 0 : h / w > 0 ? 3 : 2];
            while ((h | w) != 0) { k[b.X + w + W * (b.Y + h)] = s; h -= h.CompareTo(0); w -= w.CompareTo(0); }
            k[a.X + a.Y * W] = '+';
            k[W * ++i] = '\n';
        }

        Console.Write(k);
    }
}

C#, 638 chars

using System;
using System.Linq;
using System.Text.RegularExpressions;

class C
{
    static void Main()
    {
        int i=0,j;
        var p = Console.In.ReadToEnd()
            .Split('\n')
            .SelectMany(
                r =>
                {
                    i++; j =0;
                    return Regex.Matches(r, "\\s+(\\d+)").Cast<Match>()
                    .Select(m => { j += m.Length; return new { X = j, Y = i-1, N = int.Parse(m.Groups[1].Value) }; });
                }
        ).OrderBy(a=>a.N).ToList();

        var W = p.Max(a => a.X)+1;
        var k = new char[W*i+W];
        i = 0;
        while (i < p.Count)
        {
            var b = p[i > 0 ? i - 1 : 0]; var a = p[i];
            int h = a.Y - b.Y, w = a.X - b.X;
            var s = "|-/\\"[h == 0 ? 1 : w == 0 ? 0 : h / w > 0 ? 3 : 2];
            while ((h | w) != 0) { k[b.X + w + W * (b.Y + h)] = s; h -= h.CompareTo(0); w -= w.CompareTo(0); }
            k[a.X + a.Y * W] = '+';
            k[W * ++i] = '\n';
        }

        Console.Write(k);
    }
}
z祗昰~ 2024-09-02 17:55:13

我无法在注释中进行多行操作,因此我将在这里进行演示。
在以下示例中,距离(x1,x2) == 距离(y1,y2):

+
|\
+-+

+
|\
| \
+--+

+
|\
| \
|  \
+---+

根据所解释的规则,距离(x1,x2) == 距离(y1,y2)+2:

+\
| \
+--\+

+\
| \
|  \
+---\+

+\
| \
|  \
|   \
+----\+

I cannot do multi-line in a comment, so I will demonstrate here.
In the following examples, distance(x1,x2) == distance(y1,y2):

+
|\
+-+

+
|\
| \
+--+

+
|\
| \
|  \
+---+

With the rules as explained, distance(x1,x2) == distance(y1,y2)+2:

+\
| \
+--\+

+\
| \
|  \
+---\+

+\
| \
|  \
|   \
+----\+
挽清梦 2024-09-02 17:55:13

C++ 637

#include <iostream>
#include <string>
#include <vector>
#define S(x)((x)<0?-1:x>0?1:0)
using namespace std;enum{R=100,C=100,D=100};int main(){string s;
int N[D][2],M=0,q=0,p=0,i,j,V,L,a,b;for(i=0;j=0,(i<R)&&getline(cin,s);i++)
while((j=s.find_first_not_of(" ",j))<=s.size()){L=sscanf(&s[j],"%d",&V);
N[V][0]=i;N[V][1]=j;if(M<V)M=V;if(q<=i)q=i+1;if(p<=j)p=j+1;j+=L+1;}
string F(q*p,' '),l="\\|/-+-/|\\";F[p*N[1][0]+N[1][1]]='+';for(i=2;i<=M;++i){
int r=N[i-1][0],c=N[i-1][1],d=N[i][0],e=N[i][1];for(a=S(d-r),b=S(e-c);r!=d||c!=e;)
r+=a,c+=b,F[p*r+c]=l[(a+1)*3+b+1];F[p*r+c]='+';}for(i=0;i<q;i++)
cout<<string(&F[i*p],p)+"\n";}

缩进,并带有一些稍微更有意义的名称,看起来像:

#include <iostream>
#include <string>
#include <vector>
#define S(x)((x)<0?-1:x>0?1:0)
using namespace std;
enum{R=100,C=100,D=100};
int main(){
    string s;
    int N[D][2],M=0,rs=0,cs=0,i,j,V,L,dr,dc;
    for(i=0;j=0,(i<R)&&getline(cin,s);i++)
        while((j=s.find_first_not_of(" ",j))<=s.size()){
            L=sscanf(&s[j],"%d",&V);
            N[V][0]=i;
            N[V][1]=j;
            if(M<V)M=V;
            if(rs<=i)rs=i+1;
            if(cs<=j)cs=j+1;
            j+=L+1;
        }
    string F(rs*cs,' '),lines="\\|/-+-/|\\";
    F[cs*N[1][0]+N[1][1]]='+';
    for(i=2;i<=M;++i){
        int r=N[i-1][0],c=N[i-1][1],rt=N[i][0],ct=N[i][1];
        for(dr=S(rt-r),dc=S(ct-c);r!=rt||c!=ct;)
            r+=dr,c+=dc,F[cs*r+c]=lines[(dr+1)*3+dc+1];
        F[cs*r+c]='+';
    }
    for(i=0;i<rs;i++)
        cout<<string(&F[i*cs],cs)+"\n";
}

尽管表面上有差异,但它是对 morotspaj 代码的公然盗窃。

C++ 637

#include <iostream>
#include <string>
#include <vector>
#define S(x)((x)<0?-1:x>0?1:0)
using namespace std;enum{R=100,C=100,D=100};int main(){string s;
int N[D][2],M=0,q=0,p=0,i,j,V,L,a,b;for(i=0;j=0,(i<R)&&getline(cin,s);i++)
while((j=s.find_first_not_of(" ",j))<=s.size()){L=sscanf(&s[j],"%d",&V);
N[V][0]=i;N[V][1]=j;if(M<V)M=V;if(q<=i)q=i+1;if(p<=j)p=j+1;j+=L+1;}
string F(q*p,' '),l="\\|/-+-/|\\";F[p*N[1][0]+N[1][1]]='+';for(i=2;i<=M;++i){
int r=N[i-1][0],c=N[i-1][1],d=N[i][0],e=N[i][1];for(a=S(d-r),b=S(e-c);r!=d||c!=e;)
r+=a,c+=b,F[p*r+c]=l[(a+1)*3+b+1];F[p*r+c]='+';}for(i=0;i<q;i++)
cout<<string(&F[i*p],p)+"\n";}

Indented, and with a few slightly more meaningful names, that looks like:

#include <iostream>
#include <string>
#include <vector>
#define S(x)((x)<0?-1:x>0?1:0)
using namespace std;
enum{R=100,C=100,D=100};
int main(){
    string s;
    int N[D][2],M=0,rs=0,cs=0,i,j,V,L,dr,dc;
    for(i=0;j=0,(i<R)&&getline(cin,s);i++)
        while((j=s.find_first_not_of(" ",j))<=s.size()){
            L=sscanf(&s[j],"%d",&V);
            N[V][0]=i;
            N[V][1]=j;
            if(M<V)M=V;
            if(rs<=i)rs=i+1;
            if(cs<=j)cs=j+1;
            j+=L+1;
        }
    string F(rs*cs,' '),lines="\\|/-+-/|\\";
    F[cs*N[1][0]+N[1][1]]='+';
    for(i=2;i<=M;++i){
        int r=N[i-1][0],c=N[i-1][1],rt=N[i][0],ct=N[i][1];
        for(dr=S(rt-r),dc=S(ct-c);r!=rt||c!=ct;)
            r+=dr,c+=dc,F[cs*r+c]=lines[(dr+1)*3+dc+1];
        F[cs*r+c]='+';
    }
    for(i=0;i<rs;i++)
        cout<<string(&F[i*cs],cs)+"\n";
}

Despite superficial differences, it's a blatant theft of morotspaj's code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文