数字链接谓词


27

问题:

您的任务是确定一个数字序列中的每个数字是否至少包含其前一个数字。

例如,以下应返回真实:

[1, 12, 203, 0, 30]
             ^   ^ Contains a 0
        ^ Contains a 2
    ^ Contains a 1

以下应返回false:

[1, 32, 23, 34]
    ^ Doesn't contain a 1, therefore false

您的提交可以是功能或完整程序。

输入:

输入可以是任何合理的序列类型。数字数组,字符串数组,定界数字字符串等。

但是,顺序很重要,因此,无论您选择接受什么结构作为输入,显然都必须具有确定的顺序。

输入可以通过stdin或作为参数。

您可以假设:

  • 所有数字都是非负整数

  • 输入将始终包含至少2个数字

  • 输入数字将不会以0开头

输出:

输出将是一个真值或假值(由您的语言定义),表示是否满足上述规范。

测试之间的真实/虚假值不需要保持一致。

它可以输出到标准输出或返回。

测试用例:

True cases:
[1, 1, 1, 11, 111, 11, 1]
[12, 23, 34, 45, 56]
[65, 54, 43, 32, 21]
[123, 29, 9, 59, 55, 52, 2017, 2]
[1234567890, 19, 95, 5012, 23]

False cases:
[1, 2, 3, 4, 5, 1, 11] (2 doesn't contain a 1)
[12, 23, 33, 45] (45 doesn't contain a 3)
[98, 87, 76, 11, 12, 23] (11 doesn't contain a 7 or 6)

这是代码高尔夫球,因此获胜的字节数最少。

Answers:


7

果冻5 4字节

f2\Ạ

输入是一个字符串数组。

在线尝试!

怎么运行的

f2\Ạ  Main link. Argument: A (array of strings)

 2\   Pairwise reduce by:
f       Filter, yielding all chars in the left string that appear in the right one.
   Ạ  All; yield 1 if all strings are non-empty, 0 if not.


12

视网膜25 20字节

(.).*¶(?=.*\1)

^.+$

在线尝试!

每当我们找到一个在下一个数字中也出现的数字时,就会删除这些数字之间的分隔符(以及前一个数字中的数字,从共享的一个数字开始,但这无关紧要)。如果在此过程中删除了所有分隔符,则输入有效,我们通过确保字符串可以作为单行进行匹配来进行检查。


11

Brachylog,9个字节

{⊇ᵐ=∧?t}ˡ

在线尝试!

请注意,这不仅适用于整数列表,而且适用于字符串列表或列表列表。

说明

{      }ˡ       Left fold on the input:
 ⊇ᵐ=              It is possible to find a number which is a subset of both input numbers
    ∧             (and)
     ?t           The output is the second number (to continue the fold)

2
这很酷。似乎...声明性的?就像您只是在告诉语言规范一样。
Carcigenicate 2017年

3
@Carcigenicate Brachylog确实是声明性的,它基于声明性逻辑编程语言Prolog
致命

2
实际上,当我获得无限的空闲时间时,我的语言列表(越来越多)实际上就是在学习序言。有太多很棒的语言!
Carcigenicate

8

JavaScript(ES6),47 44 * 43字节

@Neil节省了一个字节

x=>x.every(y=>y.match(`[${p}]`,p=y),p=1/19)

将输入作为字符串列表。

测试片段

* 划掉的44仍然是常规的44


难道`[${p}]`不行?
尼尔

@Neil不是每个数组的第一项。
ETHproductions 2017年

啊,我看到您找到了一种解决方法。我已经知道了a=>a.reduce((l,r)=>`${l}`.match(`[${r}]`)&&r)(它也适用于数字输入)。
尼尔

p&&如果您设置了,也许可以删除p=1/19
尼尔

@Neil I,嗯...恩...那是个天才,谢谢:-)
ETHproductions

6

05AB1E,10个字节

ü‚vy`Så1åP

在线尝试! 或作为测试套件

说明

ü‚          # map pairing over each pair in input
  v         # for each pair
   y`       # push as 2 separate elements on stack
     Så     # check each digit in 2nd number for membership in first
       1å   # check if any 1 exists in the resulting list
         P  # product of stack

€Sü.å-我希望这能像我想的那样工作。
魔术章鱼缸

@carusocomputing:是的,那太好了。或者只是ü.å€Süå
Emigna

为什么成对再次不使用点命令?
Magic Octopus Urn'Mar

1
@carusocomputing:仅实现将下一个字节作为命令。它没有考虑点。
Emigna

6

CJam18 15 14字节

感谢Martin Ender,节省了4个字节

l~Afb_1>.&:,:*

在线尝试!

说明

l~              e# Read and eval the input
  Afb           e# Convert each number to a list of digits
     _          e# Duplicate the array
      1>        e# Slice it after the first element
        .&      e# Vectorized set intersection; take the set intersection of corresponding 
                e#  elements of the two arrays
          :,    e# Get the length of each intersection
            :*  e# Take the product of the whole array. 
                e#  Will be 0 if any intersection was empty.

6

Haskell,51 48 35字节

-3个字节感谢@NickHansen!我真的需要和那些monad运算符一起变得更好

-4和-9个字节分别感谢@Laikoni和@nimi!

and.(zipWith(any.flip elem)=<<tail)

这个版本将输入作为一个字符串数组,消除了对的需要show,但据我所知,它的工作方式与旧版本大致相同:

all(\(x,y)->any(`elem`x)y).(zip=<<tail).map show

(我相当确定我可以提交这样的匿名函数,但如有必要,我会予以解决)

首先,数字将转换为字符串。然后,monad magic zip=<<tail创建了一个将列表本身压缩的函数,该函数将每个条目与其邻居配对。然后all将一个lambda映射到每一对,以检查一个字符串是否包含来自另一个字符串的任何字符,最后检查它们是否全部出来True

基本上以相同方式工作的旧版本:

f a=and$zipWith(\b->any(`elem`show b).show)a$tail a

我能够通过使用zip和一些(->)monad欺骗来剃一个字节:f(x,y)= any('elem'x)y; g = all f。(zip = << tail).map show 。编辑:elem应该(希望很明显)在反引号中,但是注释格式化程序是不可能的。
尼克·汉森

44位元组:and.(zipWith(any.flip elem)=<<tail).map show
Laikoni

允许将输入作为字符串列表,例如["1234567890", "19", "95", "5012", "23"],因此您可以删除.map show
nimi

5

Mathematica 62 47 35字节

感谢MartinE,节省了12个字节。

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&[{{1},{1,2},{2,0,3},{0},{3,1}}]

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&[{{1},{1,2},{2,0,3},{0},{3,0}}]

真正


4

Ruby,49个48字节

->x{x.each_cons(2){|z|x&&=z*' '=~/(.).* .*\1/};x}

输出nil为false,“随机”整数为true。


4

Java 8,94 90 87字节

输入是代表数字的字符串数组。从第二个字符串开始,它对每个先前的字符串执行一个正则表达式比较,以查看它是否包含任何字符:.*[previous string].*

打高尔夫球:

a->{int r=1,i=0;while(++i<a.length)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}

取消高尔夫:

public class NumberChainingPredicate {

  public static void main(String[] args) {
    System.out.println("Expect true:");
    for (String[] input : new String[][] { { "1", "1", "1", "11", "111", "11", "1" }, { "12", "23", "34", "45", "56" },
        { "65", "54", "43", "32", "21" }, { "123", "29", "9", "59", "55", "52", "2017", "2" },
        { "1234567890", "19", "95", "5012", "23" } }) {
      System.out.println(java.util.Arrays.toString(input) + " = " + exec(f(), input));
    }

    System.out.println();
    System.out.println("Expect false:");
    for (String[] input : new String[][] { { "1", "2", "3", "4", "5", "1", "11" }, { "12", "23", "33", "45" },
        { "98", "87", "76", "11", "12", "23" } }) {
      System.out.println(java.util.Arrays.toString(input) + " = " + exec(f(), input));
    }
  }

  private static java.util.function.Function<String[], Boolean> f() {
    return a -> {
      int r = 1, i = 0;
      while (++i < a.length) {
        r *= a[i].matches(".*[" + a[i - 1] + "].*") ? 1 : 0;
      }
      return r > 0;
    };
  }

  private static boolean exec(java.util.function.Function<String[], Boolean> function, String[] input) {
    return function.apply(input);
  }

}

真好!比我要发布的要短很多。.总之,您可以打更多的高尔夫球:a->{for(int i=1;i<a.length;)if(!a[i].matches(".*["+a[i++-1]+"].*"))return 0>1;return 1>0;}90个字节
Kevin Cruijssen

我也打了90球,但方式却不同:a->{int r=1;for(int i=0;++i<a.length;)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}
Business Cat

1
没关系,到了87:a->{int r=1,i=0;for(;++i<a.length;)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}
商务猫

感谢你们俩。我认为,现在以有意义的数量改善此问题的唯一方法是查看正则表达式。

4

果冻,6个字节

Dµf"ḊẠ

在线尝试!

说明

Dµf"ḊẠ
Dµ        Treat the first (i.e. only) input as a list of decimal digits
   "      For each pair of corresponding elements in {the input digits} and
    Ḋ     {the input digits} with the first element removed
  f       take all elements common to both sides
     Ạ    then return true if the result has no empty lists, false otherwise

尝试在2/此处使用是最明显的方法,但是它会在所有大小为2的切片上"Ḋ运行一函数。在所有成对的相邻元素上有效地运行二进制函数,这意味着我们可以f直接使用(而不需要将其转换为一元函数)的功能f/)。最终会保留输入的最后一个元素,但是幸运的是,即使输入0转换为十进制时也不会成为空列表,因此它对无效



3

果冻,8 字节

Dœ&L¥2\Ạ

在线尝试!

怎么样?

Dœ&L¥2\Ạ - Main link: the list of integers            e.g. [3, 13, 351, 73, 82]
D        - convert all the integers to decimal lists       [[3],[1,3],[3,5,1],[7,3],[8,2]]
     2\  - 2-slice cumulative reduce with:
    ¥    -     last two links as a dyad:
 œ&      -         multiset intersection                   [[3],[1,3],[3],[]]
         -         length                                  [1,2,1,0]
       Ạ - all truthy?                                     0


2

PowerShell,87字节

param($n)(1..($a=$n.length-1)|?{[char[]]$n[($i=$_)-1]|?{$n[$i]-like"*$_*"}}).count-eq$a

在线尝试!

从任何方面来看,这都不是最短的,但是与其他人所使用的方法却略有不同,并且展示了漂亮的方法。 |?{}功能。

这会将输入作为字符串数组放入$n,然后从循环1length-1。我们使用Where-Object|?{...})提取对于特定条件是正确的那些索引。您可以将其for视为带有if子句的组合循环。

这里的子句是 [char[]]$n[($i=$_)-1]|?{$n[$i]-like"*$_*"}。也就是说,我们要获取当前索引$_,将其设置为$i,然后减去1,然后使用它来索引$n(即,这样我们就可以在输入数组中获得前一个元素)。然后将其char强制转换为-array并通过另一个Where-Object过程发送。

内子句$n[$i]-like"*$_*"指定当前索引处的串$i-like当前字符$_从一索引。因此,这将输出两个数组元素之间共有的任何字符。因此,仅当存在共同字符时,outer子句才会为真(因为在PowerShell中,空数组为false),因此仅当存在共同字符时才选择索引。

然后,我们收集所有符合条件的索引,并验证 .count其是否-eq与输入数组的长度一致。该布尔结果留在管道上,并且输出是隐式的。




2

PHP,65 68

for(;null!==$a=$argv[++$i+1];)$r+=$a==strtr($a,$argv[$i],_);echo!$r;

遍历所有数字并删除前一个数字中出现的所有数字。计算它等于数字本身的频率(不删除数字)。如果至少有一个相等,那么我们在一对中就没有匹配。


修复了使用triminsted的错误strtr。感谢@JörgHülsermann


很抱歉。对于给定的测试用例,您的解决方案有效。["filename",1,11,414]不起作用。
约尔格Hülsermann

@JörgHülsermann当然trim只适用于前导和尾随字符。固定它。
克里斯多夫(Christoph)

对于PHP <7.1,可以使用a&代替null!==(-5字节)。
泰特斯

...但这仅适用于中的第一个数字$argv[$i],因为“如果从和具有不同的长度,则忽略两者中较长者的多余字符。” (来自手册)
Titus

2

PHP,75字节

for($b=3**39;--$argc;)preg_replace("#[$b]#","",$b=$argv[$argc])<$b?:die(1);

从命令行参数获取数字;1出于虚假而退出,出于真相0而退出。在线
运行-r或对其进行测试

  • 从...开始 $b =包含所有数字的数字
  • 遍历参数
    • 删除的所有数字 $b从参数中
    • 复制参数到 $b
    • 如果没有删除数字,请退出 1
  • 隐式:退出 0

1

PHP,77字节

for($i=$t=1;++$i<$argc;)$t*=preg_match("#[{$argv[$i-1]}]#",$argv[$i]);echo$t;

1
备选:foreach($argv as$k=>$v)$t=$k--?$t*preg_match("#[{$argv[$k]}]#",$v)):1;echo$t;,77个字节(未测试)。
Ismael Miguel

1
@IsmaelMiguel重型替代首先,你必须改变$k--,以--$k与下降后的),你的做法应该工作,你必须添加一个@的警告
约尔格Hülsermann

哦,是的,没有注意到导致语法错误的无用的括号。我不同意这个$k--。我专门使用它,以便在第一次运行时$ k仍为0。警告是可忽略的。这意味着代码现在是76个字节,但仍未经测试。
Ismael Miguel

编辑后,我可以确认它foreach($argv as$k=>$v)$t=$k--?$t*preg_match("#[{$argv[$k]}]#",$v):1;echo$t;是否可以正常工作。按预期进行显示测试和$argv = array(1, 12, 123, 3, 34, 45, 5, 5);显示 1测试。$argv = array(1, 12, 123, 3, 34, 45, 5, 6);0
Ismael Miguel

@IsmaelMiguel您忘记了中的第一个参数是文件名。
约尔格Hülsermann

1

MATL,14个字节

1&)"V@VX&nv@]x

在线尝试!

感谢@LuisMendo节省了一个字节。说明:

1&)            % 'Pop' the first item from the input and push it on the stack.
   "       ]   % Main 'for' loop, to loop over the rest of the input.
    V            % Stringify previous (or first) iten from the input.
     @V          % Push current number, convert to string
       X&        % Intersect with stringified number already on the stack.
         nv      % Count the size of the intersection, and add it to the existing list of sizes.
           @     % Push the current number again for the intersection in the next loop. 
             x % Remove the number pushed by the last loop.
               % Else the program would end with the result on the second instead of the first position in the stack

您可以保存一个字节替换1)VG1&)(这样可以避免重复第一个数字)
Luis Mendo

@LuisMendo当然!我模糊地记得MATL具有此功能,但是在规范中搜索“ pop”(例如在队列或堆栈中)并没有产生任何结果,所以我认为我错了。
桑奇斯

是的,实际上这是引用索引的一种特殊情况。对于两个输出,参考索引操作)将给定的值作为第一个输出,然后将其余值作为第二个输出
Luis Mendo

@LuisMendo聪明。他们应该雇用您的MATL专家来改善MATLAB ...
Sanchises

哈哈。有时我确实错过了MATLAB中的某些功能
Luis Mendo

1

Clojure,71个字节

(fn[n](every?(fn[[q w]](some q w))(partition 2 1(map #(set(str %))n))))

接受数字序列的匿名函数。退货true/false

我喜欢它的读法。这里肯定有一些地方可以改进。我传递给的函数map不容易更改,因此不需要函数宏,这意味着整个函数无法利用宏,因为宏可能会增加一些字节。如果我能找到一种更好的方法来解译every?谓词中的值,那也将是一件很好的事情。

(defn number-chain? [nums]
  (let [; Turn each number into a set of characters
        set-nums (map #(set (str %)) nums)

        ; Partition the sets into lists of neighbors
        ; [1 2 3 4] -> [[1 2] [2 3] [3 4]]
        partitioned (partition 2 1 set-nums)]

    ; Does every second neighbor contain some element of the first?
    (every?
      (fn [[l1 l2]]
        (some l1 l2))
      partitioned)))

1

SimpleTemplate,124个字节

哇,这是锻炼!

{@eachargv asA keyK}{@ifK}{@setR"/[",O,"]/"}{@calljoin intoR"",R}{@ifA is notmatchesR}{@return}{@/}{@/}{@setO A}{@/}{@echo1}

这“简单地”使用旧元素制作正则表达式,显示1为真实值,否则不显示任何值。


取消高尔夫:

{@each argv as number key K}
    {@if K}
        {@set regex "/[", old, "]/"}
        {@call join into regex "", regex}
        {@if number is not matches regex}
            {@return false}
        {@/}
    {@/}
    {@set old number}
{@/}
{@echo 1}

1

JavaScript(ES6),37个字节

s=>/^(.*(.).*\n(?=.*\2))+.+$/.test(s)

接受输入,以一串用换行符分隔的数字表示。基于@ MartinEnder♦出色的Retina答案,但是因为它在JavaScript中更短,所以可以在一个正则表达式中完成整个测试。


1

12 10字节

$&B@X^_MPg

将输入作为一系列命令行参数。输出为真值的非空列表,为假值的空列表。在线尝试验证所有测试用例

说明

         g  List of all cmdline args
       MP   Map this function to consecutive pairs of items from that list:
     ^_      Split 1st item of pair into list of characters
    X        Convert to regex that matches any of those characters
  B@         Find all matches in 2nd item of pair
$&          Fold on logical AND--truthy if all items are truthy, falsey if one is falsey
            Print (implicit)

1

Röda45 35字节

{[_=~`(\S*(\S)\S* (?=\S*\2))+\S+`]}

在线尝试!

这类似于Perl 5解决方案,它是Martin Ender的Retina解决方案的移植版。-10个字节感谢@Neil。

这是一个不同的解决方案(73 72字节):

{[_/""]|{|x|{x|[0]()unless[not(_ in y)]else[1]}if tryPeek y}_|sum|[_=0]}

这是一个匿名函数,可从流中提取字符串并检查连续的字符串是否包含相同的字符。说明:

{
    [_/""]|    /* split strings -> creates arrays of characters */
    {|x|       /* begin for loop over character arrays */
        {      /* begin if tryPeek(y) -> peeks the second item from the stream */
               /* x and y are now two consecutive character arrays */
            x| /* push characters in x to the stream */
            [0]()unless[not(_ in y)]else[1] /* pushes 0 to the stream */
                                            /* if y contains the character */
                                            /* in the stream, otherwise 1 */
        }if tryPeek y
    }_|        /* end for loop */
    sum|       /* sum all numbers in the stream */
    [_=0]      /* return true if the sum is zero */
}

它可能会打更多...


拥有一个一次性进行整个测试的正则表达式会有所帮助吗?有点像^(\S*(\S)\S* (?=\S*\2))+\S+$
尼尔

@Neil似乎有效。谢谢!
fergusq

1

Bash + Unix实用程序,71 69字节

sed "s/\(.*\)/<<<\1 \&\&grepx[\1]/;1s/.*g/g/;\$s/ .*//"|tr 'x
' \ |sh

在线尝试!

输入在stdin上,每行一个数字。

输出在退出代码中:0表示真实,1表示虚假。

这可能打得更多。

为使以上代码正常工作,当前目录中不能有任何文件名为一位的文件。如果这是不可接受的,请[\1]在程序中替换为'[\1]'(另需2个字节)。

样本运行(挑战中提供的最后一个测试用例):

$ echo '98
> 87
> 76
> 11
> 12
> 23' | ./digittest > /dev/null; echo $?
1

(这里有1个是错误的。)


怎么运行的:

我将在上面运行的示例中进行演示。

sed命令将输入​​转换为:

grepx[98]
<<<87 &&grepx[87]
<<<76 &&grepx[76]
<<<11 &&grepx[11]
<<<12 &&grepx[12]
<<<23

然后tr命令将其转换为字符串:

grep [98] <<<87 &&grep [87] <<<76 &&grep [76] <<<11 &&grep [11] <<<12 &&grep [12] <<<23

该字符串是用于执行所需操作的shell命令,因此我将其通过管道传递到sh并完成。


文件限制很好,尽管那肯定是一个奇怪的限制。
Carcigenicate

1

Q,57个字节

{r::();({r,::any(last x)in y;x,enlist y}\)($)0,x;all 1_r}
  1. 初始化全局r。
  2. 将输入转换为字符串数组。
  3. 扫描数组,检查最后一个字符串中的某些字符是否在当前字符串中。
  4. 将每个结果附加到r。
  5. 如果所有字符串都满足步骤3,则返回1,否则返回0。

注意:函数内输入数组的开头附加了0。这样做是为了完成第一个元素的比较。否则,将获取第一个元素的最后一个字符以进行比较。可以进行类型检查,但是会在当前计数上增加7个字节。


这看起来与我的Clojure回答类似。看起来很整洁的语言。
Carcigenicate
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.