代码之家  ›  专栏  ›  技术社区  ›  Frank Perez

数组搜索代码挑战

  •  10
  • Frank Perez  · 技术社区  · 7 年前

    以下是我的(代码高尔夫)挑战: 取两个字节数组,确定第二个数组是否是第一个数组的子字符串。如果是,则输出第二个数组的内容在第一个数组中出现的索引。如果在第一个数组中找不到第二个数组,则输出-1。

    { 63, 101, 245, 215, 0 } { 245, 215 }

    预期产出:2

    示例输入2:{24,55,74,3,1}{24,56,74}

    预期产出2:-1

    编辑: 有人指出bool是冗余的,所以函数所要做的就是返回一个int,表示值的索引,如果找不到,则返回-1。

    34 回复  |  直到 17 年前
        1
  •  12
  •   Vatine    17 年前

    公共lisp:

    (defun golf-code (master-seq sub-seq)
      (search sub-seq master-seq))
    
        2
  •  8
  •   fooledbyprimes    17 年前

    J

    全部的 匹配索引。

    I.@(([-:#@[{.>@])"_ 0(<@}."0 _~i.@#))
    

    用法:

       NB. Give this function a name
       i =: I.@(([-:#@[{.>@])"_ 0(<@}."0 _~i.@#))
       NB. Test #1
       245 215 i 63 101 245 215 0
    2
       NB. Test #2 - no results
       24 56 74 i 24 55 74 3 1
    
       NB. Test #3: matches in multiple locations
       1 1 i 1 1 1 2 1 1 3
    0 1 4
       NB. Test #4: only exact substring matches
       1 2 i 0 1 2 3 1 0 2 1 2 0
    1 7
    

    NB. list[0 to end], list[1 to end], list[2 to end], ...
    <@}."0 _~i.@#
    
    NB. Does the LHS completely match the RHS (truncated to match LHS)?
    [-:#@[{.>@]
    
    NB. boolean list of match/no match
    ([-:#@[{.>@])"_ 0(<@}."0 _~i.@#)
    
    NB. indices of *true* elements
    I.@(([-:#@[{.>@])"_ 0(<@}."0 _~i.@#))
    
        3
  •  7
  •   balpha    17 年前

    后记 146 170 166 167 159个字符 (在“完成工作”部分):

    % define data
    /A [63 101 245 215 0] def
    /S [245 215] def
    
    % do the work
    /d{def}def/i{ifelse}d/l S length 1 sub d/p l d[/C{dup[eq{pop -1}{dup S p
    get eq{pop p 0 eq{]length}{/p p 1 sub d C}i}{p l eq{pop}if/p l d C}i}i}d
    A aload pop C
    
    % The stack now contains -1 or the position
    

    请注意,这样可以找到 最后的 如果子阵列包含多次,则子阵列发生。

    修订历史:

    • false 通过 [[ne true 通过 [[eq 保存三个字符
    • 删除了一个错误,如果 S A
    • 使错误修复更便宜,节省了四个字符
    • 必须再次插入空格,因为破折号是名称中的合法字符。未捕获此语法错误,因为测试用例未达到此点。
    • 停止返回布尔值,因为OP不再需要它们。节省8个字符。

    解释版本:

    不幸的是,SO语法荧光笔不知道PostScript,因此可读性仍然有限。

    /A [63 101 245 215 0] def
    /S [245 215 ] def
    
    /Slast S length 1 sub def % save the index of the last element of S,
                              % i.e. length-1
    /Spos Slast def % our current position in S; this will vary
    [ % put a mark on the bottom of the stack, we need this later.
    
    /check % This function recursively removes values from the stack
           % and compares them to the values in S
    {
      dup [ 
      eq
      { % we found the mark on the bottom, i.e. we have no match
        pop -1 % remove the mark and push the results
      }
      { % we're not at the mark yet
        dup % save the top value (part of the bugfix)
        S Spos get
        eq 
        {  % the top element of the stack is equal to S[Spos]
           pop % remove the saved value, we don't need it
           Spos 0
           eq 
           { % we are at the beginning of S, so the whole thing matched.
             ] length % Construct an array from the remaining values
                      % on the stack. This is the part of A before the match,
                      % so its length is equal to the position of the match.
                      % Hence we push the result and we're done.
           }
           { % we're not at the beginning of S yet, so we have to keep comparing
             /Spos Spos 1 sub def % decrease Spos
             check % recurse
           }
           ifelse
        }
        { % the top element of the stack is different from S[Spos]
          Spos Slast eq {pop} if % leave the saved top value on the stack
                                 % unless we're at the end of S, because in
                                 % this case, we have to compare it to the
                                 % last element of S (rest of the bugfix)
          /Spos Slast def % go back to the end of S
          check % recurse
        }
        ifelse
     }
     ifelse
    }
    def % end of the definition of check
    
    A aload % put the contents of A onto the stack; this will also push A again,
            % so we have to ...
    pop % ...remove it again
    check % And here we go!
    
        4
  •  6
  •   Chris Ballance    17 年前

    C99

    #include <string.h>
    
    void find_stuff(void const * const array1, const size_t array1length, /* Length in bytes, not elements */
                    void const * const array2, const size_t array2length, /* Length in bytes, not elements */
                    char * bReturnBool,
                    int * bReturnIndex)
    {
        void * found = memmem(array1, array1length, array2, array2length);
        *bReturnBool = found != NULL;
        *bReturnIndex = *bReturnBool ? found - array1 : -1;
    }
    

    用速记,以及 一点 更混乱的是:

    #include <string.h>
    #define f(a,b,c,d,e,f) { void * g = memmem(a, b, c, d); f = (e = !!g) ? g - a : -1; }
    
        5
  •  5
  •   Stephan202    9 年前

    Python 2&3. 73 68 58个字符

    基于 Nikhil Chelliah answer kaiser.se answer :

    >>> t=lambda l,s:''.join(map(chr,l)).find(''.join(map(chr,s)))
    >>> t([63, 101, 245, 215, 0], [245, 215])
    2
    >>> t([24, 55, 74, 3, 1], [24, 56, 74])
    -1
    

    Python 3, 36个字符

    多亏了 gnibbler :

    >>> t=lambda l,s:bytes(l).find(bytes(s))
    >>> t([63, 101, 245, 215, 0], [245, 215])
    2
    >>> t([24, 55, 74, 3, 1], [24, 56, 74])
    -1
    

    哈斯克尔, 68 64个字符

    OP指定的参数顺序:

    import List;t l s=maybe(-1)id$findIndex id$map(isPrefixOf s)$tails l
    

    ephemient 指出,我们可以切换参数并将代码减少四个字符:

    import List;t s=maybe(-1)id.findIndex id.map(isPrefixOf s).tails
    
        6
  •  4
  •   Paul Wicks asgeo1    17 年前

    在Python中:

    def test(large, small):
        for i in range(len(large)):
            if large[i:i+len(small)] == small:
                return i
        return -1
    

    但既然人们想要简洁,而不是优雅:

    def f(l,s):
     for i in range(len(l)):
      if l[i:i+len(s)]==s:return i
     return -1
    

    这是75个字符,包括空格。

        7
  •  4
  •   Lars Haugseth    16 年前

    def bytearray_search(a,b)
      (i=b.pack('C*').index(b.pack('C*')))?i:-1
    end
    

    Perl(36个字符的正文,不包括参数处理):

    sub bytearray_search {
      ($a,$b) = @_;
      index(pack('C*',@$a),pack('C*',@$b))
    }
    
        8
  •  3
  •   Stig Brautaset    17 年前

    我觉得我在作弊,但使用Perl这会满足OP的要求:

    sub byte_substr {
        use bytes;
        index shift,shift
    }
    

    正常地 index() 在Perl中,使用字符语义处理字符串,但“use bytes”pragma使其使用byte segmanics。从手册页:

    结果,编码被暂时忽略,并且每个字符串都被处理 作为一系列字节。

        9
  •  3
  •   Nick Dandoulakis    17 年前

    def subarray(large, small):
        strsmall = ' '.join([str(c).zfill(3) for c in small])
        strlarge = ' '.join([str(c).zfill(3) for c in large])
        pos = strlarge.find(strsmall)
        return  ((pos>=0), pos//4)
    
        10
  •  3
  •   Gibbons    17 年前

    Ruby 1.9(44B)

    _=->a,b{[*a.each_cons(b.size)].index(b)||-1}
    
    p _[[63, 101, 245, 215, 0], [245, 215]]
    p _[[24, 55, 74, 3, 1], [24, 56, 74]]
    

    高鲁比(29B)

    _=->a,b{a.e_(b.sz).dx(b)||-1}
    
        11
  •  2
  •   fortran    17 年前

    python

    def f(a,b):
     l=[a[i:i+len(b)]for i in range(len(a))]
     return b in l and l.index(b)or-1
    

    序言

    s(X,[]).
    s([H|T],[H|U]):-s(T,U).
    f(X,Y,0):-s(X,Y).
    f([_|T],Y,N):-f(T,Y,M),N is M+1.
    
        12
  •  2
  •   u0b34a0f6ae    16 年前

    Python oneliner函数定义,64个字符

    def f(l,s): return ''.join(map(chr,l)).find(''.join(map(chr,s)))
    

    因为我们被明确地通过了 字节数组 我们可以将其转换为Python的原生字节数组 str 和使用 str.find

        13
  •  2
  •   John La Rooy    16 年前

    Python3 36字节

    基于Stephan202

    >>> t=lambda l,s:bytes(l).find(bytes(s))
    ... 
    >>> t([63, 101, 245, 215, 0], [245, 215])
    2
    >>> t([24, 55, 74, 3, 1], [24, 56, 74])
    -1
    
        14
  •  1
  •   jwoolard    17 年前

    在Python中:

    def SearchArray(input, search):
    found = -1
    for i in range(0, len(input) - len(search)):
        for j in range(0, len(search)):
            if input[i+j] == search[j]:
                found = i
            else:
                found = -1
                break
    if  found >= 0:
        return True, found
    else:
        return False, -1
    

    检验

    print SearchArray([ 63, 101, 245, 215, 0 ], [ 245, 215 ])
    print SearchArray([ 24, 55, 74, 3, 1 ], [ 24, 56, 74 ])
    

    (True, 2)
    (False, -1)
    

    注意,有一个较短的解决方案,但它使用的python语言特性并不是真正可移植的。

        15
  •  1
  •   Fredrik Mörk    17 年前

    在C#中:

    private object[] test(byte[] a1, byte[] a2)
    {
        string s1 = System.Text.Encoding.ASCII.GetString(a1);
        string s2 = System.Text.Encoding.ASCII.GetString(a2);
        int pos = s1.IndexOf(s2, StringComparison.Ordinal);
        return new object[] { (pos >= 0), pos };
    }
    

    用法示例:

    byte[] a1 = new byte[] { 24, 55, 74, 3, 1 };
    byte[] a2 = new byte[] { 24, 56, 74 };
    object[] result = test(a1, a2);
    Console.WriteLine("{0}, {1}", result[0], result[1]); // prints "False, -1"
    
        16
  •  1
  •   2 revs, 2 users 67%<br/>Anhar&#13; &#13;    17 年前
    public class SubArrayMatch
    {
        private bool _IsMatch;
        private int _ReturnIndex = -1;
        private List<byte> _Input;
        private List<byte> _SubArray;
        private bool _Terminate = false;
    #region "Public Properties"
        public List<byte> Input {
            set { _Input = value; }
        }
    
        public List<byte> SubArray {
            set { _SubArray = value; }
        }
    
        public bool IsMatch {
            get { return _IsMatch; }
        }
    
        public int ReturnIndex {
            get { return _ReturnIndex; }
        }
    #endregion
    #region "Constructor"
        public SubArrayMatch(List<byte> parmInput, List<byte> parmSubArray)
        {
            this.Input = parmInput;
            this.SubArray = parmSubArray;
        }
    #endregion
    #region "Main Method"
        public void MatchSubArry()
        {
            int _MaxIndex;
            int _Index = -1;
            _MaxIndex = _Input.Count - 1;
    
            _IsMatch = false;
    
            foreach (byte itm in _Input) {
                _Index += 1;
    
                if (_Terminate == false) {
                    if (SubMatch(_Index, _MaxIndex) == true) {
                        _ReturnIndex = _Index;
                        _IsMatch = true;
                        return;
                    }
                }
                else {
                    return;
                }
            }
        }
    
        private bool SubMatch(int BaseIndex, int MaxIndex)
        {
            int _MaxSubIndex;
            byte _cmpByte;
            int _itr = -1;
    
            _MaxSubIndex = _SubArray.Count - 1;
            _MaxSubIndex += 1;
    
            if (_MaxSubIndex > MaxIndex) {
                _Terminate = true;
                return false;
            }
    
            foreach (byte itm in _SubArray) {
                _itr += 1;
    
                _cmpByte = _Input(BaseIndex + _itr);
    
                if (!itm == _cmpByte) {
                    return false;
                }
            }
    
            return true;
        }
    #endregion
    
    }
    

    安哈尔·侯赛因·米亚 编辑:Anhar.Miah@:03/07/2009

        17
  •  1
  •   lucasweb    17 年前

    在105年。。。

    function a_m($h,$n){$m=strstr(join(",",$h),join(",",$n));return$m?(count($h)-substr_count($m,",")-1):-1;}        
    

    或者更明确地说,

    function array_match($haystack,$needle){
      $match = strstr (join(",",$haystack), join(",",$needle));
      return $match?(count($haystack)-substr_count($match,",")-1):-1;
    }
    
        18
  •  1
  •   Christoph    17 年前

    GNU C:

    int memfind(const char * haystack, size_t haystack_size, const char * needle,
        size_t needle_size)
    {
        const char * match = memmem(haystack, hasystack_size, needle, needle_size);
        return match ? match - haystack : -1;
    }
    

    ANSI C,不带库:

    int memfind(const char * haystack, size_t haystack_size, const char * needle,
        size_t needle_size)
    {
        size_t pos = 0;
        for(; pos < haystack_size; ++pos)
        {
            size_t i = 0;
            while(pos + i < haystack_size && i < needle_size &&
                haystack[pos + i] == needle[i]) ++i;
    
            if(i == needle_size) return pos;
        }
    
        return -1;
    }
    
        19
  •  1
  •   ashwnacharya    17 年前

    红宝石

    class Array
      def contains other=[]
        index = 0
        begin
          matched = 0
          ndx = index
          while other[matched] == self[ndx]
            return index if (matched+1) == other.length
            matched += 1
            ndx += 1
          end
        end until (index+=1) == length
        -1
      end
    end
    
    puts [ 63, 101, 245, 215, 0 ].contains [245, 215]
    # 2
    puts [ 24, 55, 74, 3, 1 ].contains [24, 56, 74 ]
    # -1
    
        20
  •  1
  •   Toby Deshane    17 年前

    C#,称为“a”和“b”的列表:

    Enumerable.Range(-1, a.Count).Where(n => n == -1 
        || a.Skip(n).Take(b.Count).SequenceEqual(b)).Take(2).Last();

    如果您不关心返回第一个实例,可以执行以下操作:

    Enumerable.Range(-1, a.Count).Last(n => n == -1 
        || a.Skip(n).Take(b.Count).SequenceEqual(b));
        21
  •  1
  •   3 revs, 2 users 85%<br/>user196115&#13;    13 年前
    int m(byte[]a,int i,int y,byte[]b,int j,int z){return i<y?j<z?a[i]==b[j++]?m(a,++i,y,b,j,z):m(a,0,y,b,j,z):-1:j-y;}
    

    Java,116个字符。添加了一点额外的功能。好的,所以将开始条件和数组长度推送到调用者中是一个难题。可以这样说:

    m(byte[] substring, int substart, int sublength, byte[] bigstring, int bigstart, int biglength)
    
        22
  •  0
  •   BubbleSort    9 年前

    Fredrik 已使用字符串转换方式发布代码。这里有另一种使用C#的方法。

    jwoolard 顺便说一句,我也用过和他一样的算法。这是我们在大学里用C++解决的问题之一。

    public static bool Contains(byte[] parent, byte[] child, out int index)
    {
        index = -1;
    
        for (int i = 0; i < parent.Length - child.Length; i++)
        {
            for (int j = 0; j < child.Length; j++)
            {
                if (parent[i + j] == child[j])
                    index = i;
                else
                {
                    index = -1;
                    break;
                }
            }
        }
    
        return (index >= 0);
    }
    
        23
  •  0
  •   Tom SW    17 年前

    (defun byte-array-subseqp (subarr arr)
      (let ((found (loop 
                      for start from 0 to (- (length arr) (length subarr))
                      when (loop 
                              for item across subarr
                              for index from start below (length arr)
                              for same = (= item (aref arr index))
                              while same
                              finally (return same))
                      do (return start))))
        (values (when found t) ; "real" boolean
                (or found -1))))
    

    Lisp v2(注意,subseq创建一个副本

    (defun byte-array-subseqp (subarr arr)
      (let* ((alength (length arr))
             (slength (length subarr))
             (found (loop 
                       for start from 0 to (- alength slength)
                       when (equalp subarr (subseq arr start (+ start slength)))
                       do (return start))))
        (values (when found t)
                (or found -1))))
    
        24
  •  0
  •   user132748    17 年前

    public static object[] isSubArray(byte[] arr1, byte[] arr2) {
      int o = arr1.TakeWhile((x, i) => !arr1.Skip(i).Take(arr2.Length).SequenceEqual(arr2)).Count();
      return new object[] { o < arr1.Length, (o < arr1.Length) ? o : -1 };
    }
    
        25
  •  0
  •   Cuervo's Laugh    17 年前

    在Ruby中:

    def subset_match(array_one, array_two)
      answer = [false, -1]
      0.upto(array_one.length - 1) do |line|
        right_hand = []
        line.upto(line + array_two.length - 1) do |inner|
          right_hand << array_one[inner]
        end
        if right_hand == array_two then answer = [true, line] end
      end
      return answer
    end
    

    内部评级(主要):151:0>子集_匹配([24,55,74,3,1],[24,56,74]) =>[错,-1]

    =>[对,2]

        26
  •  0
  •   Jason    17 年前

    first
      .Select((index, item) => 
        first
         .Skip(index)
         .Take(second.Count())
         .SequenceEqual(second) 
        ? index : -1)
      .FirstOrDefault(i => i >= 0)
      .Select(i => i => 0 ? 
         new { Found = true, Index = i } 
        : 
         new { Found = false, Index - 1 });
    
        27
  •  0
  •   ken    17 年前
    (defun golf-code (master-seq sub-seq)
      (let ((x (search sub-seq master-seq)))
        (values (not (null x)) (or x -1))))
    
        28
  •  0
  •   baker1990    17 年前

    哈斯克尔(114个字符):

    import Data.List
    import Data.Maybe
    g a b | elem b $ subsequences a = fromJust $ elemIndex (head b) a | otherwise = -1
    
        29
  •  0
  •   please delete me    17 年前

    Ruby看到Lar的代码后我觉得很惭愧

    def contains(a1, a2)
      0.upto(a1.length-a2.length) { |i| return i if a1[i, a2.length] == a2 }
      -1
    end
    
        30
  •  0
  •   LukeH    17 年前

    int FindSubArray(byte[] super, byte[] sub)
    {
        int i = BitConverter.ToString(super).IndexOf(BitConverter.ToString(sub));
        return i < 0 ? i : i / 3;
    }
    
    // 106 characters
    int F(byte[]x,byte[]y){int i=BitConverter.ToString(x)
    .IndexOf(BitConverter.ToString(y));return i<0?i:i/3;}
    

    这里有一个稍微长一点的版本,它对每个单独的数组元素执行真正的比较。

    int FindSubArray(byte[] super, byte[] sub)
    {
        int i, j;
        for (i = super.Length - sub.Length; i >= 0; i--)
        {
            for (j = 0; j < sub.Length && super[i + j] == sub[j]; j++);
            if (j >= sub.Length) break;
        }
        return i;
    }
    
    // 135 characters
    int F(byte[]x,byte[]y){int i,j;for(i=x.Length-y.Length;i>=0;i--){for
    (j=0;j<y.Length&&x[i+j]==y[j];j++);if(j>=y.Length)break;}return i;}
    
    推荐文章