寻找遗失的信件


27

指导方针

任务

编写一个方法,该方法将一个连续(递增)的字母数组作为输入,并返回该数组(某些语言的列表)中缺少的字母。


规则

  • 这是代码高尔夫球,所以最短答案以字节为单位!
  • 您将始终获得有效的数组
  • 总是会丢失一个字母
  • 数组的长度将始终至少为2。
  • 数组将始终仅在一种情况下(大写或小写)包含字母
  • 您必须输出与输入相同的大小写(大写或小写)
  • 该数组一次总是只发送一个字母(跳过丢失的字母)
  • 数组长度在2到25之间
  • 数组的第一个或最后一个元素将永远不会丢失

例子

['a','b','c','d','f'] -> 'e'

['O','Q','R','S'] -> 'P'

['x','z'] -> 'y'

['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','w','x','y','z'] -> 'v'


我可以代替一个字符串吗?
Leaky Nun

@LeakyNun字符串是字符数组,所以可以。
阿莫里斯'17

1
输出可以是包含缺失字符的数组吗(例如:对于input ['a','b','c','d','f','g'],output ['e'],如果这会使代码更短?
Xcoder先生

1
@ Mr.Xcoder字符串只是一个字符数组,所以是
Amorris

2
规则4只是规则8的子集,可以删除(至少,如果在规则8的末尾加上“ inclusive”一词)。
NH。

Answers:



11

C#(.NET Core)48 47 46字节,作为字符数组输入

s=>{for(int i=0;s[++i]==++s[0];);return s[0];}

在线尝试!

说明:数组中的第一个元素递增,并且指针迭代随后的元素。当第一个元素和当前元素都不相同时,它将返回第一个元素。

C#(.NET Core)58 56 50字节,作为字符串输入

s=>{var c=s[0];while(s.IndexOf(++c)>=0);return c;}

在线尝试!

以前的58字节解决方案(在第一个注释中引用):

s=>{for(int i=1;;i++)if(s[i]-s[0]>i)return(char)(s[i]-1);}

使用System.Linq的算法

以下算法必须using System.Linq;在字节数上增加(18个字节),因此更长。

我非常喜欢这个(52 + 18字节):

s=>{int i=0;return(char)(s.First(c=>c-s[0]>i++)-1);}

而且您还有一个单线(45 + 18)字节的解决方案:

s=>(char)(s.Where((c,i)=>c-s[0]>i).First()-1)

还有一个非常聪明的(37 + 18)字节的解决方案,由Ed'ka提供:

s=>s.Select(e=>++e).Except(s).First()

1
并非所有代码路径都不返回值会导致编译失败?但是+1的比较检查s[i]-s[0]非常聪明!
TheLethalCoder

@TheLethalCoder它不会失败,因为for循环没有停止条件,因此它将一直迭代直到if条件评估为true
查理

1
您可以这样保存8个字节:(a=>{int i=0;for(;a[++i]-a[0]<=i;);return--a[i];}当您将输入作为时char[])。顺便说一句,谢谢我,感谢@NevayJava 8答案的评论。
凯文·克鲁伊森

1
@KevinCruijssen找到了一种方法,可以将另外两个字节保存为char数组作为输入。
查理

1
更短的Linq版本:s=>s.Select(e=>++e).Except(s).First()
Ed'ka

8

爱丽丝,10字节

/X.
\ior@/

在线尝试!

说明

这只是线性程序的框架,这些程序完全以Ordinal(字符串处理)模式运行:

/...
\.../

实际的线性代码如下:

i.rXo@

哪个:

i   Read all input.
.   Duplicate.
r   Range expansion. If adjacent letters don't have adjacent code points, the
    intermediate code points are filled in between them. E.g. "ae" would turn
    into "abcde". For the inputs in this challenge, this will simply insert
    the missing letter.
X   Symmetric set difference. Drops all the letters that appear in both strings,
    i.e. everything except the one that was inserted by the range expansion.
o   Output the result.
@   Terminate the program.


7

Ruby,21个字符

->a{[*a[0]..a[-1]]-a}

根据问题所有者的返回单个元素数组 评论

样品运行:

irb(main):001:0> ->a{[*a[0]..a[-1]]-a}[['a','b','c','d','f']]
=> ["e"]

在线尝试!


7

Java 8,70 57 56 48 46字节

a->{for(int i=0;++a[0]==a[++i];);return a[0];}

@CarlosAlejo使 -14(70→56)和-2(48→46)字节。@Nevay使得
-8(56→48)个字节。

说明:

在这里尝试。

a->{            // Method with char-array parameter and char return-type
  for(int i=0;  //  Start index-integer at 0 and loop as long as
    ++a[0]      //   the previous character + 1 (by modifying the character at index 0)
    ==a[++i];   //   equals the next character (by raising the index by 1 before checking)
  );            //  End of loop
  return a[0];  //  Return the now modified character at index 0 in the array
}               // End of method

1
您可以使用隐式强制转换而不是显式强制转换来节省8个字节a->{int i=0;for(;a[++i]-a[0]<=i;);return--a[i];}
涅瓦

6

C(gcc),3335 36 48 60 个字节

应该关闭所有优化功能,并且只能在32位GCC上使用。

f(char*v){v=*v+++1-*v?*v-1:f(v);}

将输入作为字符串。

在线尝试!


2
“应该关闭所有优化功能,并且只能在32位GCC上使用。” 是一个非常
round回

我会说foo(char*a){return*a+1==a[1]?foo(a+1):++*a;}还不错。仅比更自然的字符短1个字符foo(char*a){while(*a+1==a[1])a++;return++*a;}
sehe

@sehe恒定的未定义行为在PPCG上被接受
Gan

5

Python 3中74个 62 58 44 40字节

-12个字节感谢Outgolfer的Erik。-18个字节感谢Leaky Nun。-4字节,感谢musicman523。

将输入作为字节串。

lambda s:chr(*{*range(s[0],s[-1])}-{*s})

在线尝试!

另一个很酷的解决方案:

lambda s:chr(*{*range(*s[::~-len(s)])}-{*s})

1
.difference({*s})->-{*s}
暴民埃里克(Erik the Outgolfer)'17年




1
Your solution is what I was after but in a far more elegant way
Pureferret

4

Mathematica, 46 bytes

Min@Complement[CharacterRange@@#[[{1,-1}]],#]&

I believe that Min@Complement[CharacterRange@@#[[{1,-1}]],#]& would save a byte.
LegionMammal978

@LegionMammal978 actually 2!
J42161217

3

JavaScript (ES6), 70 bytes

Input as a character array

(a,p)=>a.some(c=>(q=p+1,p=c.charCodeAt(),p>q))&&String.fromCharCode(q)

Less golfed

a=>{
  p = undefined;
  for(i = 0; c = a[i]; i++)
  {
    q = p+1
    p = c.charCodeAt()
    if (p>q)
      return String.fromCharCode(q)
  }
}

Test

F=(a,p)=>a.some(c=>(q=p+1,p=c.charCodeAt(),p>q))&&String.fromCharCode(q)

function update() {
  var a0=A0.value.charCodeAt()
  var a1=A1.value.charCodeAt()
  if (a1>a0) {
    var r = [...Array(a1-a0+1)]
      .map((x,i)=>String.fromCharCode(a0+i))
      .filter(x => x != AX.value)
    I.textContent = r.join('') + " => " + F(r)
  }
  else {
    I.textContent=''
  }
}

update()
input { width: 1em }
Range from <input id=A0 value='O' pattern='[a-zA-Z]' length=1 oninput='update()'>
to <input id=A1 value='T' pattern='[a-zA-Z]' length=1 oninput='update()'>
excluding <input id=AX value='Q' pattern='[a-zA-Z]' length=1 oninput='update()'>
<pre id=I></pre>



3

Retina, 33 25 bytes

$
¶$_
T`p`_p`.*$
D`.
!`.$

Try it online! Works with any range of ASCII characters. Edit: Saved 8 bytes thanks to @MartinEnder. Explanation: The first stage duplicates the input. The second decreases all of the characters in the copy by 1 code point. The third stage deletes all of the characters in the copy that still appear in the original. This just leaves the original input, the character that precedes the first character of the original input and the missing character. The last stage then just matches the missing character.


Here is 25, using the same basic idea: tio.run/##K0otycxL/P9fhevQNpV4rpCEgoT4ggQ9LRUulwQ9LsUEPZX///… (I'm decrementing the second line because that saves a byte and then I'm finding the unique char using deduplication.)
Martin Ender

@MartinEnder Deduplication is exactly what I wanted all along, and I already forgot Retina has it, sigh... (I know incrementing the first line takes a byte more than decrementing the second line but it made the match regex shorter.)
Neil

3

SWI Prolog, 124 bytes

m([H|T]):-n(H,N),c(T,N),!,m(T).
n(I,N):-o(I,C),D is C+1,o(N,D).
c([N|_],N).
c(_,N):-print(N),!,fail.
o(C,O):-char_code(C,O).

Examples:

?- m(['a','b','c','d','f']).
e
false.

?- m(['O','Q','R','S']).
'P'
false.

?- m(['x','z']).
y
false.

?- m(['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','w','x','y','z']).
v
false.

Little explanation:

The m is the "main" procedure,the n produces next expected character in the list. The c does comparison - if expectation matches the next item, continue, else print out expected character and jump out of the window.


1
Shorter than fail: 0=1.
mat

3

C++14, standard library, generic container type (87 86 bytes)

[](auto a){return++*adjacent_find(begin(a),end(a),[](auto a,auto b){return a+1!=b;});}

Container type from namespace ::std is assumed (e.g. std::string, std::list or std::vector. Otherwise using namespace std; or similar would be assumed.

Thanks to @Ven, with a little bit of preprocessor hacking, you get get it down to 82 bytes (1 newline)

#define x [](auto a,int b=0){return++
x *adjacent_find(begin(a),end(a),x a!=b;});}

See it Live On Coliru

C++14 no standard library (still generic, 64 63 bytes)

[](auto& a){auto p=*begin(a);for(auto c:a)if(c!=p++)return--p;}

Again, need to help name lookup only if container type not from namespace ::std (or associated with it)

Live On Coliru for std::string e.g.

Live On Coliru for char const[] e.g.


You need to put a space between the strike-out text and the next text.
CJ Dennis

@CJDennis Done. By the way, your current rep (2469) is a beautiful number (being 3*823 and also visually paired as (24)(69) which is (2 2 2 3)(3 23))
sehe

2

Charcoal, 18 bytes

Fγ¿¬∨∨‹ι⌊θ›ι⌈θ№θιι

Try it online! Link is to verbose version of code. Takes input as a string. Works with any almost contiguous sequence of ASCII characters.


2

C#, 104 bytes

using System.Linq;a=>(char)Enumerable.Range(a.Min(),a.Max()-a.Min()).Except(a.Select(c=>(int)c)).First()

Full/Formatted version:

using System.Linq;

namespace System
{
    class P
    {
        static void Main()
        {
            Func<char[], char> f = a =>
                (char)Enumerable.Range(a.Min(), a.Max() - a.Min())
                                .Except(a.Select(c=>(int)c))
                                .First();

            Console.WriteLine(f(new[] { 'a', 'b', 'c', 'd', 'f' }));

            Console.ReadLine();
        }
    }
}

A very clever Linq version by Ed'ka: s=>s.Select(e=>++e).Except(s).First()
Charlie

@CarlosAlejo I saw you added it to your answer so I won't update mine but yes it is very clever. A lot shorter than my version of doing it.
TheLethalCoder

2

MATL, 8 7 bytes

1 byte saved thanks to @Luis

tdqf)Qc

Try it at MATL Online

Explanation

      % Implicitly grab the input as a string
t     % Duplicate the string
d     % Compute the differences between successive characters
q     % Subtract 1 from each element
f     % Get the locations of all non-zero characters (1-based index)
)     % Extract that character from the string
Q     % Add one to get the next character (the missing one)
c     % Convert to character and display

@LuisMendo Awesome, thanks!
Suever

2

Excel, 110 + 2 = 112 bytes

=CHAR(CODE(LEFT(A1))-1+MATCH(0,IFERROR(FIND(CHAR(ROW(INDIRECT(CODE(LEFT(A1))&":"&CODE(RIGHT(A1))))),A1),0),0))

Must be entered as an array formula (Ctrl+Shift+Enter) which adds curly brackets { } on each end, adding two bytes. Input is as a string in A1, which is OK per OP.

This is not the shortest answer by far (Excel rarely is) but I like seeing if it can be done.



2

CJam, 6 bytes (full program) / 7 bytes (code block)

q),^W=

Try it online!

This is a full CJam program that reads the input string from standard input and prints the missing letter to standard output. CJam doesn't actually have "methods", which is what the challenge asks for, but the closest thing would probably be an executable code block, like this:

{),^W=}

Try it online!

This code block, when evaluated, takes the input as a string (i.e. an array of characters) on the stack, and returns the missing character also on the stack.


Explanation: In the full program, q reads the input string and places it on the stack. ) then pops off the last character of the input string, and the range operator , turns it into an array containing all characters with code points below it (including all letters before it in the alphabet). Thus, for example, if the input was cdfgh, then after ), the stack would contain the strings cdfg (i.e. the input with the last letter removed) and ...abcdefg, where ... stands for a bunch of characters with ASCII codes below a (i.e. all characters below the removed last input letter).

The symmetric set difference operator ^ then combines these strings into a single string that contains exactly those characters that appear in one of the strings, but not in both. It preserves the order in which the characters appear in the strings, so for the example input cdfg, the result after ),^ will be ...abe, where ... again stands for a bunch of characters with ASCII codes below a. Finally, W= just extracts the last character of this string, which is exactly the missing character e that we wanted to find (and discards the rest). When the program ends, the CJam interpreter implicitly prints out the contents of the stack.


Bonus: GolfScript, 6 bytes (full program)

),^-1>

Try it online!

It turns out that nearly the same code also works in GolfScript. We save one byte in the full program version due to GolfScript's implicit input, but lose one byte because, unlike CJam's W, GolfScript doesn't have a handy single-letter variable initialized to -1.

Also, CJam has separate integer and character types (and strings are just arrays containing characters), whereas GolfScript only has a single integer type (and has a special string type that behaves somewhat differently from normal arrays). The result of all this is that, if we want the GolfScript interpreter to print out the actual missing letter instead of its ASCII code number, we need to return a single-character string instead of just the character itself. Fortunately, making that change here just requires replacing the indexing operator = with the array/string left truncation operator >.

Of course, thanks to GolfScript's implicit I/O, the code above can also be used as a snippet that reads a string from the stack and returns a single-character string containing the missing letter. Or, rather, any snippet that takes a single string on the stack as an argument, and returns its output as a printable string on the stack, is also a full GolfScript program.


6
Code snippets are not allowed by default; only functions and full programs are. So you probably need that q (program), or {...} (block). +1 for the approach though
Luis Mendo

This is very clever!
Esolanging Fruit

2

Husk, 6 bytes

→S-(ḣ→

Try it online!

This function takes a string (list of characters) as input, and returns a character as output.

Explanation

→S-(ḣ→
    ḣ→    Get the list of all characters from the null byte to the last character of the input
 S-       Subtract the input from this list
→         Get the last element of the result

2

Python 2 - 76 bytes

Loses to existing python 2 solution but it's a slightly different approach so I thought I'd post it anyway:

lambda c:[chr(x)for x in range(ord(c[0]),ord(c[0]+26)if chr(x)not in c][0]

2

8th, 99 bytes

Rationale

If the distance between letters is greater than two, then there is a missing letter. Letter distance is obtained by computing the difference between ASCII code of each letter.

Code

: f ' nip s:each repeat over n:- 2 n:= if n:1+ "" swap s:+ . reset 1 then depth n:1- while! reset ;

Ungolfed version

: f \ s -- c 
  ' nip s:each    \ convert each letter into its ASCII code and put them on stack
  repeat
    over
    n:- 2 n:=     \ check if there is a missing letter 
    if            
      n:1+        \ compute the ASCII code of missing letter
      "" swap s:+ \ convert ASCII code into printable character
      .           \ print out the missing letter
      reset 1     \ set condition to exit from while!
    then
    depth n:1-    \ verify if there are letters to check
  while!          
  reset           \ clean stack
;

Usage and examples

ok> "abcdf" f
e
ok> "OQRS" f
P
ok> "xz" f
y
ok> "abcdefghijklmnopqrstuwxyz" f
v
ok> "ab" f

ok> "def" f

ok>

2

JavaScript (ES6), 64 bytes

Takes input as a string.

s=>(g=p=>(c=String.fromCharCode(n++))<s[p]?p?c:g(p):g(p+1))(n=0)

How?

  • Initialization: We start with n = 0 and p = 0 and call the recursive function g().

    g = p =>                                   // given p
      (c = String.fromCharCode(n++)) < s[p] ?  // if the next char. c is not equal to s[p]:
        p ?                                    //   if p is not equal to zero:
          c                                    //     step #3
        :                                      //   else:
          g(p)                                 //     step #1
      :                                        // else:
        g(p + 1)                               //   step #2
  • Step #1: We increment n until c = String.fromCharCode(n) is equal to the first character of the input string s[0].

  • Step #2: Now that we're synchronized, we increment both n and p at the same time until c = String.fromCharCode(n) is not equal to s[p] anymore.

  • Step #3: We return c: the expected character which was not found.

Test cases


1

J, 20 bytes

{&a.>:I.1 0 1&E.a.e.
  • a.e. boolean mask for the input letters across ascii charset
  • 1 0 1&E. new boolean mask indicating if the sequence 101 begins at that index, ie, find any place a "skip" sequence begins
  • I. the index of that match, ie, the character before the skipped one
  • >: increment by 1, ie, the index of the skipped char within ascii charset
  • {&a. pick that index from the ascii charset, ie, return the skipped char

Try it online!


That looks like a snippet to me.
Adám

@Adám It's written in a tacit (point-free) style, which I believe counts as "function-like" as opposed to a snippet. As best as I can tell, it's no more of a snippet than your APL solution is (but I do not know dyalog, so take what I say with a grain of salt).
zgrep

@Adám yes it is, in the sense that it can’t be assigned to a variable but assumes input on its right side. is this not legal? i asked about it somewhere and was told it was fine
Jonah

My understanding for APL/J/K is that the code must be able to reside in a name, whether by assignment or as the body an explicit verb/function (however, the explicit form must then have explicit input too). Snippet is code which assumes values in variables and/or needs pasting into a line, but cannot stand on their own.
Adám

@zgrep No, this code is explicit (non-tacit), but is missing the reference to its argument on the far right. My APL function is a complete tacit function which can assigned or put in a parenthesis.
Adám

1

ES6, 125 bytes:

(a=>((s,f)=>(r=(i,b)=>a[i]?r(i+1,b||(s[f](i)-s[f](i-1)-1&&String.fromCharCode(s[f](i-1)+1))):b)(1,0))(a.join(""),"charCodeAt"))

http://jsbin.com/vasoqidawe/edit?console

The returned function needs to be called with an array

(["a","c"])

one could save another 9 bytes through removing .join("") and passing a string:

("ac")

ES6, 108 bytes:

(a=>((s,f,o)=>(a.find((_,i)=>(o?++o:o=s[f](i))!==s[f](i)),String.fromCharCode(o)))(a.join(""),'charCodeAt'),0))

http://jsbin.com/tudiribiye/edit?console


1
bind ??? in code golf ?
edc65

@edc65 whats wrong with it ? ( sorry if this is n00b, but thats my first golf :))
Jonas Wilms

@edc65 but youre probably right, removing it saved 4 bytes...
Jonas Wilms

a.join("") could be a.join``
user2428118

1

Common Lisp, 88 bytes

(lambda(s)(loop as(x y)on s if(>(#1=char-code y)(1+(#1#x)))return(code-char(1+(#1#x)))))

Try it online!


1

Python 2, 69 bytes

lambda a:chr((ord(a[0])+ord(a[-1]))*-~len(a)/2-sum(ord(x)for x in a))

Try it online!

Some explanations As we know the first and the last elements of the list, we can easily compute the sum of the codes of all the chars in the list + the missed char (using summary formulas of arithmetic progression). The difference between this sum and the sum of the codes of all the chars in the list gives the code of the missed letter.



1

APL (Dyalog), 17 bytes

(⊃⎕AV/⍨∨\∧~)⎕AV∘∊

Try it online!

⎕AV∘∊ Boolean: each character in the Atomic Vector (character set) member of the argument?

() apply the following tacit function:

 the first element of

⎕AV the Atomic Vector (the character set)

/⍨ which

∨\ follows the initial (member of the argument)

 but

~ is not (a member of the argument)

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.