挑战:最短的代码,按字符计数,检测并删除字符串中的重复字符。删除包括重复字符的所有实例(因此,如果您找到 3 个 n,则所有三个都必须删除),并且需要保留原始字符顺序。
示例输入 1:
nbHHkRvrXbvkn示例输出 1:
RrX
示例输入 2:
nbHHkRbvnrXbvkn示例输出 2:
RrX
(第二个示例删除了出现三次的字母;一些解决方案未能解决此问题)
(这是基于我的另一个问题,我需要在 C# 中以最快的方式执行此操作,但我认为它可以跨语言制作良好的 Code Golf。)
perl 的 21 个字符,调用 31 个字符,总共 36 个击键(计算移位和最终返回):
perl -pe's/$1//gwhile/(.).*\1/'
61 个字符,统治者说。(给了我另一个代码高尔夫的想法……)
puts ((i=gets.split(''))-i.select{|c|i.to_s.count(c)<2}).join
+-------------------------------------------------------------------------+
|| | | | | | | | | | | | | | | |
|0 10 20 30 40 50 60 70 |
| |
+-------------------------------------------------------------------------+
gets.chars{|c|$><<c[$_.count(c)-1]}
... 35 由 Nakilon
23 个字符:
(((1+ρx)-(ϕx)ιx)=xιx)/x
我是 APL 新手(昨天才知道),所以请客气——这当然不是最有效的方法。我很惭愧我没有击败 Perl。
再说一次,当一个新手在 APL 中解决这个问题的最自然的方法仍然比迄今为止任何语言中的任何其他解决方案更简洁时,也许它说明了什么。
s=raw_input()
print filter(lambda c:s.count(c)<2,s)
这是一个完整的工作程序,可以读写控制台。单行版本可以直接从命令行使用
python -c 's=raw_input();print filter(lambda c:s.count(c)<2,s)'
J(16 12 个字符)
(~.{~[:I.1=#/.~)
例子:
(~.{~[:I.1=#/.~) 'nbHHkRvrXbvkn'
RrX
它只需要括号默认执行。如果放在动词中,实际代码本身将是 14 个字符。
当然有更聪明的方法可以做到这一点。
编辑:有问题的更聪明的方式:
(~.#~1=#/.~) 'nbHHkRvrXbvkn'
RrX
12 个字符,如果设置在动词中,则只有 10 个。我仍然讨厌它遍历列表两次的事实,一次用于计数 (#/.),另一次用于返回唯一值(nub 或 ~.),但即使是 nubcount,'misc' 库中的标准动词也会执行两次。
在 Haskell 中肯定有更短的方法可以做到这一点,但是:
Prelude Data.List> let h y=[x|x<-y,(<2).length$filter(==x)y]
Prelude Data.List> h "nbHHkRvrXbvkn"
"RrX"
忽略 let,因为它只是 GHCi 中的函数声明所必需的,所以我们有h y=[x|x<-y,(<2).length$filter(==x)y]37 个字符(这与 的当前“核心”Python 相关联"".join(c for c in s if s.count(c)<2),无论如何它实际上是相同的代码)。
如果你想用它制作一个完整的程序,
h y=[x|x<-y,(<2).length$filter(==x)y]
main=interact h
$ echo "nbHHkRvrXbvkn" | runghc tmp.hs
RrX
$ wc -c tmp.hs
54 tmp.hs
或者我们可以这样敲掉一个字符:
main=interact(\y->[x|x<-y,(<2).length$filter(==x)y])
$ echo "nbHHkRvrXbvkn" | runghc tmp2.hs
RrX
$ wc -c tmp2.hs
53 tmp2.hs
它在所有标准输入上运行,而不是逐行运行,但这似乎可以接受 IMO。
这个使用与我原来的答案完全不同的方法。有趣的是,写完之后再看另一个答案,我发现方法非常相似。感谢 caf 在我之前提出这种方法。
b[256];l;x;main(c){while((c=getchar())>=0)b[c]=b[c]?1:--l;
for(;x-->l;)for(c=256;c;)b[--c]-x?0:putchar(c);}
一行是 58+48 = 106 bytes。
这是我原来的答案。正如评论中所说,它不太好用......
#include<stdio.h>
main(l,s){char*b,*d;for(b=l=s=0;l==s;s+=fread(b+s,1,9,stdin))b=realloc(b,l+=9)
;d=b;for(l=0;l<s;++d)if(!memchr(b,*d,l)&!memchr(d+1,*d,s-l++-1))putchar(*d);}
在两行中,它是 17+1+78+77 = 173 bytes。
65 个字符:
new String(h.Where(x=>h.IndexOf(x)==h.LastIndexOf(x)).ToArray());
67 个重新分配的字符:
h=new String(h.Where(x=>h.IndexOf(x)==h.LastIndexOf(x)).ToArray());
new string(input.GroupBy(c => c).Where(g => g.Count() == 1).ToArray());
71 个字符
<?PHP
function q($x){return $x<2;}echo implode(array_keys(array_filter(
array_count_values(str_split(stream_get_contents(STDIN))),'q')));
On one line, it's 5+1+65+65 = 136 bytes. Using PHP 5.3 you could save a few bytes making the function anonymous, but I can't test that now. Perhaps something like:
<?PHP
echo implode(array_keys(array_filter(array_count_values(str_split(
stream_get_contents(STDIN))),function($x){return $x<2;})));
That's 5+1+66+59 = 131 bytes.
作为动态函数(18 个字符)
{(1+=/¨(ω∘∊¨ω))/ω}
假设输入在变量 x(16 个字符)中的行:
(1+=/¨(x∘∊¨x))/x
61 个字符。结果在哪里$s="nbHHkRvrXbvkn",在哪里$a。
$h=@{}
($c=[char[]]$s)|%{$h[$_]++}
$c|%{if($h[$_]-eq1){$a+=$_}}
功能齐全的参数化脚本:
param($s)
$h=@{}
($c=[char[]]$s)|%{$h[$_]++}
$c|%{if($h[$_]-eq1){$a+=$_}}
$a
.`{\{=}+,,(!}+,
+-------------------------------------------------------------------------+
|| | | | | | | | | | | | | | | |
|0 10 20 30 40 50 60 70 |
| |
+-------------------------------------------------------------------------+
For Each c In s : s = IIf(s.LastIndexOf(c) <> s.IndexOf(c), s.Replace(CStr(c), Nothing), s) : Next
诚然,VB 不是尝试保存字符的最佳语言,但该行最多 98 个字符。
#include-ing <stdio.h>(花费 18 个字符)使返回类型gets被解释为 anint并砍掉一半的地址位)。.
main(){char s[999],*c=gets(s);for(;*c;c++)strchr(s,*c)-strrchr(s,*c)||putchar(*c);}
(这个类似的82 -chars 版本通过命令行输入:
main(char*c,char**S){for(c=*++S;*c;c++)strchr(*S,*c)-strrchr(*S,*c)||putchar(*c);}
)
哈斯克尔
(只是从 Mark Rushakoff 的努力中删除了几个字符,我宁愿将它作为对他的评论发布)
h y=[x|x<-y,[_]<-[filter(==x)y]]
这是更好的 Haskell 习语,但对于非 Haskell 人来说可能比这更难遵循:
h y=[z|x<-y,[z]<-[filter(==x)y]]
编辑以添加对 hiena 和其他人的解释:
我假设您理解 Mark 的版本,所以我将只介绍更改。马克的表情:
(<2).length $ filter (==x) y
过滤y以获取元素列表== x,找到该列表的长度并确保它小于两个。(实际上它必须是长度一,但==1比 长<2) 我的版本:
[z] <- [filter(==x)y]
执行相同的过滤器,然后将结果列表作为唯一元素放入列表中。现在箭头(看起来像集合包含!)说“对于 RHS 列表的每个元素,依次调用该元素[z]”。[z]是包含单个元素的列表z,因此元素“ filter(==x)y”只有在[z]它包含一个元素时才能称为“”。否则它会被丢弃并且永远不会用作 的值z。所以z's(在列表理解的左侧返回|)正是x使filterreturn 成为长度为 1 的列表的 's。
那是我的第二个版本,我的第一个版本返回x而不是z- 因为它们无论如何都是相同的 - 并重命名z为_“这个值不会被使用,所以我不会使我的代码复杂化”的 Haskell 符号通过给它一个名字”。
s.split('').filter(function (o,i,a) a.filter(function(p) o===p).length <2 ).join('');
或者 - 类似于 python 示例:
[s[c] for (c in s) if (s.split("").filter(function(p) s[c]===p).length <2)].join('');
汇编器
使用 WinXP DOS 框 (cmd.exe) 测试:
xchg cx,bp
std
mov al,2
rep stosb
inc cl
l0: ; to save a byte, I've encoded the instruction to exit the program into the
; low byte of the offset in the following instruction:
lea si,[di+01c3h]
push si
l1: mov dx,bp
mov ah,6
int 21h
jz l2
mov bl,al
shr byte ptr [di+bx],cl
jz l1
inc si
mov [si],bx
jmp l1
l2: pop si
l3: inc si
mov bl,[si]
cmp bl,bh
je l0+2
cmp [di+bx],cl
jne l3
mov dl,bl
mov ah,2
int 21h
jmp l3
汇编为 53 个字节。读取标准输入并将结果写入标准输出,例如:
programname < input > output
63 个字符。
puts (t=gets.split(//)).map{|i|t.count(i)>1?nil:i}.compact.join
123 个字符。有可能让它更短,但这对我来说已经足够了。
proc h {i {r {}}} {foreach c [split $i {}] {if {[llength [split $i $c]]==2} {set r $r$c}}
return $r}
puts [h [gets stdin]]
96 个字符的完整工作声明
Dim p=New String((From c In"nbHHkRvrXbvkn"Group c By c Into i=Count Where i=1 Select c).ToArray)
完整的工作语句,带有原始字符串和 VB 特定的“漂亮列表(代码重新格式化”)关闭,在 96 个字符处,没有原始字符串的非工作语句在 84 个字符处。
(请确保您的代码在回答之前有效。谢谢。)
完整的 C 语言程序,141 字节(包括换行符)。
#include<stdio.h>
c,n[256],o,i=1;main(){for(;c-EOF;c=getchar())c-EOF?n[c]=n[c]?-1:o++:0;for(;i<o;i++)for(c=0;c<256;c++)n[c]-i?0:putchar(c);}
s.match(/(.)(?=.*\1)/g).map(function(m){s=s.replace(RegExp(m,'g'),'')})
比之前发布的 Javascript 1.8 解决方案更短(71 个字符与 85 个字符)
54 个字符仅用于方法主体,66 个带有(静态类型)方法声明:
def s(s:String)=(""/:s)((a,b)=>if(s.filter(c=>c==b).size>1)a else a+b)
C
(第一版:112 个字符;第二版:107 个字符)
k[256],o[100000],p,c;main(){while((c=getchar())!=-1)++k[o[p++]=c];for(c=0;c<p;c++)if(k[o[c]]==1)putchar(o[c]);}
那是
/* #include <stdio.h> */
/* int */ k[256], o[100000], p, c;
/* int */ main(/* void */) {
while((c=getchar()) != -1/*EOF*/) {
++k[o[p++] = /*(unsigned char)*/c];
}
for(c=0; c<p; c++) {
if(k[o[c]] == 1) {
putchar(o[c]);
}
}
/* return 0; */
}
因为 getchar() 返回 int 而 putchar 接受 int,所以可以“安全地”删除 #include。没有包含,EOF 没有定义,所以我使用 -1 代替(并获得了一个字符)。该程序仅适用于少于 100000 个字符的输入!
版本 2,感谢 strager 107 个字符
#ifdef NICE_LAYOUT
#include <stdio.h>
/* global variables are initialized to 0 */
int char_count[256]; /* k in the other layout */
int char_order[999999]; /* o ... */
int char_index; /* p */
int main(int ch_n_loop, char **dummy) /* c */
/* variable with 2 uses */
{
(void)dummy; /* make warning about unused variable go away */
while ((ch_n_loop = getchar()) >= 0) /* EOF is, by definition, negative */
{
++char_count[ ( char_order[char_index++] = ch_n_loop ) ];
/* assignment, and increment, inside the array index */
}
/* reuse ch_n_loop */
for (ch_n_loop = 0; ch_n_loop < char_index; ch_n_loop++) {
(char_count[char_order[ch_n_loop]] - 1) ? 0 : putchar(char_order[ch_n_loop]);
}
return 0;
}
#else
k[256],o[999999],p;main(c){while((c=getchar())>=0)++k[o[p++]=c];for(c=0;c<p;c++)k[o[c]]-1?0:putchar(o[c]);}
#endif
:;s/((.).*\2.*)\2/\1/;t;s/(.)(.*)\1/\2/;t
用法:$ echo nbHHkRbvnrXbvkn | sed -r ':;s/((.).*\2.*)\2/\1/;t;s/(.)(.*)\1/\2/;t'
由gnarf pyon 贡献;)。
其中 s 是您的输入字符串:
new string(s.Where(c=>s.Count(h=>h==c)<2).ToArray());
或 59 重新分配:
var a=new string(s.Where(c=>s.Count(h=>h==c)<2).ToArray());
fold -w1|sort|uniq -u|paste -s -d ''
118 个字符的实际代码(加上 PHP 块标记的 6 个字符):
<?php
$s=trim(fgets(STDIN));$x='';while(strlen($s)){$t=str_replace($s[0],'',substr($s,1),$c);$x.=$c?'':$s[0];$s=$t;}echo$x;
import Data.List
import Control.Monad
import Control.Arrow
main=interact$liftM2(\\)nub$ap(\\)nub
整个节目97个字,但真正的肉只有23个字。其余的只是导入并将函数带入 IO monad。在加载了模块的 ghci 中,它只是
(liftM2(\\)nub$ap(\\)nub) "nbHHkRvrXbvkn"
在更荒谬的无点风格(无意义的风格?):
main=interact$liftM2 ap liftM2 ap(\\)nub
虽然函数本身有 26 个字符,但它有点长。
z=#(ly:gulp-file"A")#(print(string-delete z(lambda(x)(>(string-count z x)1))))
用法:$ cp input.in A; lilypond this.ly
template F(alias s,int c,int i){static if(s>"")enum F=F!(s[1..$],c,i-(s[0]==c));else enum F=i?s:s~c;}template M(alias s,alias t=s){static if(s>"")enum M=F!(t,s[0],1)~M!(s[1..$],t);else enum M=s;}
扩展:
template F(alias s,int c,int i){
static if(s>"")
enum F=F!(s[1..$],c,i-(s[0]==c));
else
enum F=i?s:s~c;
}
template M(alias s,alias t=s){
static if(s>"")
enum M=F!(t,s[0],1)~M!(s[1..$],t);
else
enum M=s;
}
pragma(msg,M!"nbHHkRvrXbvkn");
使用 C - 118 个字符
我认为这个答案很好,因为它适用于任何字符串长度。
main(int s,char *a[]){int i=0,j,c,d;while(s=c=a[1][i]){j=0;while(d=a[1][j])if(i!=j++)if(c==d)s=0;s&&putchar(c);i++;}}
并且通过删除变量的类型定义,可以将其降至 105(我认为是新的 C 赢家:P),但我的编译器会抛出错误!
你们有什么感想?
f以最易读的格式编写,g旨在以f更简洁的方式准确再现。
小写f和g函数是“详细”的,大写F是G“压缩的”版本。
J与 相同G,但它被声明为显示完整程序所需的字符数。
removedups.lua:
f = function(s)
h=s:sub(1,1) -- head of string
r=s:sub(2) -- rest of string
if r:find(h) then -- first character is repeated
return f(s:gsub(h, '')) -- f(rest without any instance of h)
elseif r > "" then -- there is something left in the rest of the string
return h .. f(r) -- concatenate head with f(rest)
else return h -- rest is empty string, so just return value left in head
end
end
F=function(s)h=s:sub(1,1)r=s:sub(2)if r:find(h)then return f(s:gsub(h,''))elseif r>""then return h ..f(r)else return h end end
-- 1 2 3 4 5 6 7 8 9 10 11 12
--3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
-- 126 chars, compressed
g = function(s)
h=s:sub(1,1)
r=s:sub(2)
return (r:find(h) and g(s:gsub(h, '')) or (r > "" and h .. g(r)) or h)
end
G=function(s)h=s:sub(1,1)r=s:sub(2)return r:find(h)and g(s:gsub(h,''))or(r>""and h ..g(r))or h end
-- 1 2 3 4 5 6 7 8 9 10 11
--345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
-- 98 chars, compressed
-- code-golf unit tests :)
assert(f("nbHHkRvrXbvkn")=="RrX")
assert(F("nbHHkRvrXbvkn")=="RrX")
assert(g("nbHHkRvrXbvkn")=="RrX")
assert(G("nbHHkRvrXbvkn")=="RrX")
J=function(s)h=s:sub(1,1)r=s:sub(2)return r:find(h)and g(s:gsub(h,''))or(r>""and h ..g(r))or h end print(J(arg[1]))
-- 1 2 3 4 5 6 7 8 9 10 11
--34567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
-- 115 chars, full program
输出:
$ lua 删除ups.lua nbHHkRvrXbvkn RrX
来自非常冗长的语言的 165 个字符。
object c=getc(0),r={},b=r
while c>0 do
if find(c,r)then b&=c end if
r&=c
c=getc(0)
end while
for i=1 to length(r)do
if find(r[i],b)=0 then puts(1,r[i])end if
end for
具有30 个字符的 sed 版本,如果不包含命令的调用,则为21 个字符:
sed -r ':_;s/(.)(.*)\1/\2/;t_'
一个使用相同想法的java版本(应该都写在一行中),它是157个字符:
class T{public static void main(String[]a){String s=a[0];int l;
do{l=s.length();s=s.replaceAll("(.)(.*)\\1","$2");}while(s.length()<l);
System.out.printf(s);}}
i,s=1,...s:gsub('.',function(c)if s:find(c,i)then s=s:gsub(c,'')else i=i+1 end end)print(s)
OCaml,93 个字符(wc -c)。
open String
let f s=let r=ref""in iter(fun c->if not(contains!r c)then r:=!r^(make 1 c))s;!r
let f(a:string)=new string(Seq.toArray(Seq.filter(fun(c:char)->a.IndexOf c=a.LastIndexOf c)a))
printfn "%s" (f "nbHHkRvrXbvkn")
#!/usr/bin/python
# Python, 67 characters, in a giant generator.
f=lambda s:''.join([c for c in s if len([d for d in s if d==c])<2])
string = "nbHHkRvrXbvkn"
print f(string) => "RrX"
f=lambda s:''.join([c for c in s if s.count(c)<2])
i=...repeat c=i:match("(.).-%1")i=c and i:gsub(c:gsub("(%W)","%%%1"),"")or i until not c print(i)
D 编程语言第 2 版,68 个字符:
auto f(S)(S s){return array(filter!((a){return s.count(a)<2;})(s));}
1INPUT I$:FOR I=1 TO LEN(I$):S$=MID$(I$,I,1):C=0
2P=INSTR(P+1,I$,S$):C=C-(P>0):IF P GOTO 2
3IF C=1 THEN ?S$;
4NEXT
F#,使用列表的非代码高尔夫版本:
16 ilnes 使用列表:
let rec removefromlist v l =
match l with
| h::t ->
let (res, removed) = removefromlist v t
if h = v then (res, true)
else (h::res, removed)
| [] -> ([], false)
let rec removedups unique tail =
match tail with
| h::t ->
let (u_res, u_removed) = removefromlist h unique
let (t_res, t_removed) = removefromlist h t
if (t_removed || u_removed) then removedups u_res t_res
else h::removedups u_res t_res
| [] -> []
removedups [] (Array.toList("nbHHkRvrXbvkn".ToCharArray()));;
F# - 185 个字符- 没有列表的更简洁的版本:
let s = "nbHHkRvrXbvkn"
let n c (s:string)=
let mutable i = 0
for x in 0..s.Length-1 do
if s.[x]=c then i<-i+1
i
String.collect (fun c -> if n c s>1 then "" else c.ToString()) s
args1[;{},,\=/+1=]""z P
ASL 是我制作的受 Golfscript 启发的脚本语言。
我找不到原始答案,但本着 Jon Skeet 的回答:
退休储蓄计划
该程序的含义是:从标准输入(R)读取一个字符串,去除所有重复字符(S),将结果打印到标准输出(P)。