解析包裹


24

感谢您在“ 标记我的邮件”挑战中的帮助,PPCG-Post已成功地在所有包裹上盖印了生成的条形码!

现在,该解码它们了。

在此挑战中,给定从“ 标记我的邮件”挑战生成的条形码,您的程序将对其解码并返回编码的整数。

但是要当心!条码可能上下颠倒...


4状态条形码

如果您错过了编码挑战,则需要了解我们正在谈论的条形码类型。4状态条形码是一行带有四个可能状态的条,每个状态代表以4为底的整数:

            |       |
Bar:    |   |   |   |
                |   |

Digit:  0   1   2   3

条形码以ASCII呈现,将占用三行文本,使用竖线(|)字符代表条形的一部分,并使用空格()代表空白部分。每个小节之间只有一个空格。条形码示例如下所示:

| | | | | | | | | |
| | | | | | | | | | | | | | | | |
    | | | | | | | |

要将条形码转换回其编码的整数,请将每个条形码映射到其对应的以4为底的数字,将其连接起来,然后将其转换为十进制。

由于每个条形码在上下颠倒时也会代表不同的条形码,因此我们执行了一个开始/停止序列,以便可以计算方向。为了解决这一挑战,我们将使用澳大利亚邮政指定的开始/停止序列:每个条形码以一个1 0序列开头和结尾。


挑战

给定ASCII 4状态条形码,您的任务是解析它并返回它编码的整数-本质上与Mark My Mail相反。

但是要使事情变得有趣,有一个陷阱- 条形码可以上下颠倒。与现实世界一样,它将由条形码读取器(您的程序)使用开始/停止序列确定正确的方向

例:

给定以下条形码:

    | | | |
| | | | | | | | | | |
  | | | | |

我们可以清楚地看到第一对数字和最后一对数字0, 2不是1, 0。这意味着条形码是上下颠倒的-因此我们必须条形码旋转180度(而不仅仅是翻转每个条形码)以实现正确的方向:

| | | | |  
| | | | | | | | | | |
    | | | |    

现在,我们可以开始解码了。我们将每个小节映射到其对应的以4为基数的数字,而忽略开始/停止序列,因为它们不对数据进行编码。

| | | | |  
| | | | | | | | | | |
    | | | |    

--2 1 0 3 0 2 3--

我们将其连接到以4为底的整数2103023,然后将其转换为十进制表示形式9419以获得最终结果。


规则

  • 输入将始终是有效的4状态条形码,以上述ASCII格式呈现,并带有描述的开始/停止顺序。
    • 您可以索取尾随空格,带状线以及尾随换行符-无论哪种格式都适合您的高尔夫运动。
    • 它的方向可能正确或不正确-您的程序必须通过使用开始/停止顺序来确定是否将其上下颠倒读取。
    • 它将不会以4为基数的整数编码前导零数字。
  • 您可以将输入作为行列表或带换行符的字符串。
  • 输出应该是您语言的标准整数基数的整数,代表由条形码编码的数据。
  • 由于邮票很小,并且只能容纳很少的代码,因此您的代码将需要尽可能的短:这是一个 -因此,最短的程序(以字节为单位)将获胜!

测试用例

| | | | | | | | | | |
  | | |

= 4096(翻转)

      | | | | | | | |
| | | | | | | | | | | | | | | |
  | | | | | | | | | |

= 7313145(翻转)

    | | | |
| | | | | | | | | | |
  | | | | |

= 9419(翻转)

| | | | | |   
| | | | | | | | |
    | | | |     

= 990(未翻转)

| | | | |   
| | | | | | | | | | |
    | | |       

= 12345(未翻转)


-1两个帖子的标题格式不同。( “P的P” VS “M我M”,挑是'的'或'我的':P)
Rɪᴋᴇʀ

1
将“行列表”是任意的[String][{#Char}][{Char}][[Char]]?,因为String相当于{#Char}
Οurous

3
@Ouros是什么符号?我强烈怀疑答案是“是”,因为语言之间的数据类型非常不同,因此编码挑战通常会接受“无论哪种语言都可用”,但是我不知道您要表示什么不同的表示形式。
IMSoP

1
下一步是什么?发出电子邮件?传送电报?处理帖子?
桑奇斯

1
@Ourous是的,数据类型是灵活的,如IMSoP所述。
FlipTack

Answers:



5

外壳,16字节

ḋṁẊ=hhttĊ2T§▼↔m↔

在线尝试!

输入是行列表(为清楚起见,TIO链接使用多行字符串)。线必须具有相等的长度,并且不得有多余的尾随空格。

说明

ḋṁẊ=hhttĊ2T§▼↔m↔  Input is a list of strings x.
           §▼     Lexicographic minimum of
             ↔    x reversed and
              m↔  x with each line reversed.
          T       Transpose. Now we have a list of columns.
        Ċ2        Get every second column, removing the blank ones.
    hhtt          Remove first 2 and last 2 (the orientation markers).
 ṁ                Map and concatenate
  Ẋ=              equality of adjacent pairs.
                  This turns a column like "|| " into [1,0], and these pairs are concatenated.
ḋ                 Convert from binary to integer.




2

视网膜,71字节

(.).
$1
sO$^`^\|.*|.

^..|..¶.*¶..|..$
¶
\|
 |
+`\| 
 ||||
.*¶$
$&$&
\|

在线尝试!链接包括较小的测试用例。要求将第一行和最后一行用空格填充到中间行的长度。说明:

(.).
$1

删除不必要的空格。

sO$^`^\|.*|.

反转代码中的字符,但是如果条形码以开头|,则选择整个代码,否则将其拆分为字符。然后,将它们反转。如果以开头,则会翻转代码0

^..|..¶.*¶..|..$
¶

删除开始/停止序列和中间行(这对我们没有用)。

\|
 |
+`\| 
 ||||

将空格和|s从基数4 转换为一元。

.*¶$
$&$&

将最后一行加倍。

\|

转换为十进制。


2

Java(OpenJDK 8)181160字节

对于Java解决方案来说,这并不是太差劲,我敢肯定我可以做出一些优化,但是我已经盯着这个问题太久了。

通过缩短循环而不是使用子字符串来减少几个字节。

打高尔夫球

c->{String r="";Integer i,j,l=c[0].length;for(i=4;i<l-4;i+=2){j=c[0][0]>32?i:l-1-i;r+=c[0][j]%8/4*(j==i?1:2)+c[2][j]%8/4*(j==i?2:1)+"";}return l.parseInt(r,4);}

在线尝试!

不打高尔夫球

String r = "";
Integer i, j, l = c[0].length;
for(i=4; i<l-4; i+=2){
    j = c[0][0]>32 ? i : l-1-i;
    r += c[0][j]%8/4 * (j==i?1:2) + c[2][j]%8/4 * (j==i?2:1) + "";
}
return l.parseInt(r, 4);

刚刚尝试过您的代码,但使用示例“ | | |”的反向条形码 “ | | | | | | | | | | |” 并给我1024,好吧,我无法格式化该格式,但是示例中的格式,但是,请尝试使用您的示例,但不进行反转,也许我输入了错误的信息:)
Java Gonzar

@JavaGonzalezArribas我尝试了第一个示例(未翻转),它似乎运行良好。可能是您在输入的第一行中放置了太少的空格吗?
路加·史蒂文斯

那可能就是问题所在,很好的答案:)
Java Gonzar

建议l+~i而不是l-1-i
ceilingcat

2

Java的8208个 166 157 151字节

尝试一下可能会更好,减少42次不必要的检查,减少-9个变量,感谢Luke Stevens -6个

输入是一个 char[][3]

(a)->{int i=2,c,s=0;c=(a[0][0]>32)?1:-1;for(;i<a.length-2;i++){s+=((a[i][1-c]>32?1:0)+(a[i][1+c]>32?2:0))*Math.pow(4,c==1?a.length-i-3:i-2);}return s;}

松散:

int b(char[][] a) {
    int i=2,c,s=0;                      //i for looping, c to check if it's reversed, s is the sum, n the number
    c=(a[0][0]>32)?1:-1; //Check if must be reversed

    for(;i<a.length-2;i++){         //Looping elements

            //(Checking value for 1 + Checking value for 2) * Power, if reversed increasing, else decreasing
        s+=((a[i][1-c]>32?1:0)+(a[i][1+c]>32?2:0))*Math.pow(4,c==1?a.length-i-3:i-2);   
    }
    return s;
}

1
如果您使用字符数组而不是字符串,则可以检查|。通过使用> 32而不是==“ |” 每次使用可节省2个字节(总共6个)。在声明另外两个字节的lambda时,您也可以删除a周围的括号。
路加·史蒂文斯

2

干净191 ... 161个 144字节

import StdEnv
?' '=0;?_=1
r=reverse
$a b|hd a<'|'= $(r b)(r a)=[?(b!!n)*2+ ?(a!!n)\\n<-[4,6..length b-4]]
@[a,_,b]=sum[d*4^p\\d<- $a b&p<-[0..]]

在线尝试!


1

46 43 42字节

IsQ@@gg:RV*RVgY^gR'|1(J@UW2*y@2+@y)TM2FB:4

将条形码的行作为三个命令行参数。第一和第三行必须用空格填充到第二行的长度。在线尝试!

说明

首先做一些准备工作:

IsQ@@gg:RV*RVg Y^gR'|1

                        g is cmdline args; s is space (implicit)
IsQ                     If space equals
   @@g                  the first character of the first line, then:
           RVg           Reverse the order of the rows in g
        RV*              then reverse the characters in each row
      g:                 and assign the result back to g
                 gR'|1  In g, replace pipe character with 1
                ^       Split each row into a list of characters
               Y        Yank the result into y

现在观察一下,如果我们忽略中间行并将其|视为1和 0,则每个小节只是2位二进制数:

(J@UW2*y@2+@y)TM2FB:4

       y@2             Third row
     2*                Multiply by 2, turning 1 into 2 and space into 0
           @y          First row
          +            Add
   UW                  Unweave: creates a list of two lists, the first containing all
                       even-indexed elements (in our case, the actual data), the second
                       containing all odd-indexed elements (the space separators)
  @                    First item of that list
 J                     Join the list of digits into a string
(            )TM2      Trim 2 characters from the beginning and end
                 FB:4  Convert from base 4 (: makes the precedence lower than TM)
                       Autoprint

1

外壳39 38字节

B4ththmȯ%4+3%5f≠192Ḟz+zṀ·*cN?↔m↔(='|←←

将输入作为字符串列表:在线尝试尝试测试套件!

说明

B4ththm(%4+3%5)f≠192Ḟz+zṀ·*cN?↔m↔(='|←←)
                             ?   (='|←←)  -- if the very first character == '|'
                              ↔           --   reverse the lines
                                          -- else
                               m↔         --   reverse each line
                       zṀ·*cN             -- zip the lines with [1,2,3..] under..
                        Ṁ·*c              --   convert each character to its codepoint and multiply by one of [1,2,3]
                    Ḟz+                   -- reduce the lines under zipWith(+) (this sums the columns)

               f≠192                      -- only keep elements ≠ 192 (gets rid of the separating lines)

-- for the example from the challenge we would now have:
--   [652,376,468,652,376,744,376,468,744,652,376]

      m(      )                           -- map the following function
        %4+3%5                            --   λx . ((x % 5) + 3) % 4
-- this gives us: [1,0,2,1,0,3,0,2,3,1,0]
    th                                    -- remove first & last element
  th                                      -- remove first & last element
B4                                        -- interpret as base4 number

1

Perl 5、152 + 2(-F)字节

push@a,[@F]}{for$i(0..$#{$a[1]}){$_.=($a[0][$i]eq'|')+2*($a[2][$i]eq'|')}$_=reverse y/12/21/r if/^0/;s/^0*1000|10*$//g;s/.\K0//g;$\=$_+$\*4for/./g;say$\

在线尝试!


0

八度80 75 68字节

@(b)bi2de({rot90(t=~~(b-32)([3,1],[1:2:end]),2),t}{2-t(2)}(5:end-4))

在线尝试!

奇怪的是,bi2de是默认MSB右边而不是左边,导致有些头疼,而我做了这个......我想我应该有索引之前翻转数组的最佳方式,但也有非常多的方法来做到这一点(无论是在第一分度,或与flipudfliplrrot90'(转置),最终的索引......)。取一个带有空格和|s 的矩形数组(因此,需要尾随空格)

@(b)                    % Define anonymous function taking input b

t=                      % Inline-define t,
~~(b-32)                % which is the input, converted to 1's and 0's,
([3 1],[1:2:end])       % but only keep the relevant rows (1 and 3 flipped vertically) and columns (only odd) 

{rot90(t,2),t}          % Flip 180 degrees
{2-t(2)                 % depending on whether the second element of t is 1 or 0.}

(5:end-4)               % Flatten array, discarding control bits
bi2de( ... )            % and convert from binary to decimal,

0

的JavaScript(ES6),184个 181字节

我不是经验丰富的高尔夫球手-我相信这可以改善,但是我喜欢这个挑战!我一直想知道那些标记。

函数f采用带尾随空格的字符串列表。为了清楚起见,在下面的代码中添加了换行符(不包括在字节数中)。

f=t=>((o=[[...t[0]],[...t[2]]])[0][0]=='|'?o:(z=a=>a.reverse())(o.map(z)))
.map((a,r)=>a.filter((_,i)=>~i%2).map(e=>(1+r)*(e=='|')).slice(2,-2))
.reduce((a,b)=>a+parseInt(b.join``,4),0)

用法

t=['                     ','| | | | | | | | | | |','  |             |   |']
console.log(f(t)) // 4096

带说明的非高尔夫版本

// take list of strings, t, as input:
f = t => ( 

  // create output variable o, discard middle row, turn other rows into lists:
  ( o = [ [...t[0]], [...t[2]] ] )

  // if top-left position isn't a pipe, rotate 180 degrees.
  // Alias [].reverse to save 3 bytes :D
  [0][0] == '|' ? o : ( z = a=> a.reverse() )( o.map(z) )

).map( (a,r) => 

  // remove even-numbered positions (non-encoding spaces):
  a.filter( (_,i) => ~i%2 )

  // convert non-pipes into zeros, and pipes into 1 or 2;
  // top row becomes the base4 1-component, bottom row is 2:
  .map( e => (1+r) * (e=='|') ).slice(2,-2)

// convert rows to base4 component strings, then decimal, then sum them:
).reduce( (a,b) => a + parseInt(b.join``,4),0)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.