Code Golf:字符串中的重复字符删除

时间:2009-08-27 23:57:50

标签: code-golf

挑战:字符数的最短代码,用于检测并删除字符串中的重复字符。删除包括重复字符的所有实例(因此,如果您找到3个n,则所有三个必须去),并且需要保留原始字符顺序。

  

示例输入1:
     nbHHkRvrXbvkn

     

示例输出1:
     RRX


  

示例输入2:
     nbHHkRbvnrXbvkn

     

示例输出2:
     RRX

(第二个例子删除了三次出现的字母;有些解决方案没有考虑到这一点)

(这是基于my other question我需要以最快的方式在C#中执行此操作,但我认为它可以在各种语言中实现良好的Code Golf。)

48 个答案:

答案 0 :(得分:38)

LabVIEW 7.1

一个字符,这是程序框图中的蓝色常量“ 1 ”。 我发誓,输入是复制和粘贴; - )

http://i25.tinypic.com/hvc4mp.png

http://i26.tinypic.com/5pnas.png

答案 1 :(得分:26)

的Perl

perl的21个字符,31个调用,36个键击(计数移位和最终返回):

perl -pe's/$1//gwhile/(.).*\1/'

答案 2 :(得分:19)

Ruby - 61 53 51 56 35

统治者说,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

答案 3 :(得分:18)

APL

23个字符:

(((1+ρx)-(ϕx)ιx)=xιx)/x

我是一名APL新手(昨天学会了),所以请善待 - 这当然不是最有效的方式。我很惭愧,我没有太多打败Perl。

然后再说一遍,也许它说的是当新手在APL中解决这个问题的最自然方式仍然比任何其他语言的解决方案更简洁。

答案 4 :(得分:15)

的Python:

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)'

答案 5 :(得分:14)

J( 16 12个字符)

(~.{~[:I.1=#/.~)

示例:

(~.{~[:I.1=#/.~) 'nbHHkRvrXbvkn'
    RrX

只需要默认执行括号。如果放入动词,实际代码本身将是14个字符。

当然有更明智的方法可以做到这一点。

编辑:更明智的方式:

(~.#~1=#/.~) 'nbHHkRvrXbvkn'
    RrX

12个字符,如果设置为动词,则只有10个字符。我仍然讨厌这样一个事实:它通过列表两次,一次计数(#/。)而另一次返回uniques(nub或〜。),但即使是nubcount,'misc'库中的标准动词也会两次。

答案 6 :(得分:12)

的Haskell

在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个字符(这与"".join(c for c in s if s.count(c)<2)的当前“核心”Python相关联,它实际上是相同的代码无论如何)。

如果你想制作一个完整的程序,

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

它在所有的stdin上运行,而不是逐行运行,但这似乎是可以接受的IMO。

答案 7 :(得分:9)

C89(106个字符)

这个方法使用的方法与我原来的答案完全不同。有趣的是,在编写它然后查看another answer之后,我看到方法非常相似。咖啡馆在我之前提出这种方法的信用。

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字节

C89(173个字符)

这是我原来的答案。正如评论中所说的那样,效果不太好......

#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字节

答案 8 :(得分:8)

C#

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());

答案 9 :(得分:7)

C#

new string(input.GroupBy(c => c).Where(g => g.Count() == 1).ToArray());

71个字符

答案 10 :(得分:6)

另一种APL解决方案

作为动态功能(18个字符)

{(1+=/¨(ω∘∊¨ω))/ω}

行假设输入是变量x(16个字符):

(1+=/¨(x∘∊¨x))/x

答案 11 :(得分:6)

PHP(136个字符)

<?PHP
function q($x){return $x<2;}echo implode(array_keys(array_filter(
array_count_values(str_split(stream_get_contents(STDIN))),'q')));

在一行中,它是5 + 1 + 65 + 65 = 136字节。使用PHP 5.3可以节省几个字节,使函数匿名,但我现在无法测试。也许是这样的事情:

<?PHP
echo implode(array_keys(array_filter(array_count_values(str_split(
stream_get_contents(STDIN))),function($x){return $x<2;})));

那是5 + 1 + 66 + 59 = 131字节。

答案 12 :(得分:5)

C:83 89 93 99 101 字符

  • O(n 2 )时间。
  • 限制为999个字符。
  • 仅适用于32位模式(由于不是#include - <stdio.h>(费用为18个字符),因此gets的返回类型被解释为int并切掉一半的地址位。)
  • 显示友好的“警告:此程序使用gets(),这是不安全的。”在Macs上。

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);}

答案 13 :(得分:5)

VB.NET

For Each c In s : s = IIf(s.LastIndexOf(c) <> s.IndexOf(c), s.Replace(CStr(c), Nothing), s) : Next

当然,VB不是尝试保存字符的最佳语言,但该行的出现是98个字符。

答案 14 :(得分:5)

Golfscript(sym) - 15

  .`{\{=}+,,(!}+,
+-------------------------------------------------------------------------+
||    |    |    |    |    |    |    |    |    |    |    |    |    |    |  |
|0         10        20        30        40        50        60        70 |
|                                                                         |
+-------------------------------------------------------------------------+

答案 15 :(得分:5)

的PowerShell

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

答案 16 :(得分:4)

的Haskell

(只是将Mark Rushakoff的努力中的一些角色敲了一下,我宁愿把它作为对他的评论发布)

h y=[x|x<-y,[_]<-[filter(==x)y]]

这是更好的Haskell成语,但对于非Haskellers而言可能比这更难:

h y=[z|x<-y,[z]<-[filter(==x)y]]

编辑为hiena和其他人添加解释:

我假设你理解马克的版本,所以我只是介绍这个改变。马克的表达:

(<2).length $ filter (==x) y

过滤y以获取== x的元素列表,找到该列表的长度并确保它少于两个。 (实际上它必须是长度为1,但==1长于<2)我的版本:

[z] <- [filter(==x)y]

执行相同的过滤器,然后将结果列表放入列表作为唯一元素。现在箭头(看起来像集合包含!)说“依次为RHS列表的每个元素调用该元素[z]”。 [z]是包含单个元素z的列表,因此如果元素“filter(==x)y”只包含一个元素,则它只能称为“[z]”。否则它将被丢弃,并且永远不会被用作z的值。因此,z(在列表推导中|左侧返回)正好是x,使filter返回列表长度一。

这是我的第二个版本,我的第一个版本返回x而不是z - 因为它们无论如何都是相同的 - 并将z重命名为_这是Haskell符号“这个值不会被使用所以我不会通过给它命名来使我的代码复杂化。”

答案 17 :(得分:3)

Javascript 1.6

s.match(/(.)(?=.*\1)/g).map(function(m){s=s.replace(RegExp(m,'g'),'')})

比之前发布的Javascript 1.8解决方案(71 chars vs 85)

更短

答案 18 :(得分:3)

<强>汇编

使用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

答案 19 :(得分:3)

C

(第1版:112个字符;第2版: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。 没有include,EOF没有定义,所以我使用了-1代替(并获得了一个char)。 此程序仅适用于少于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

答案 20 :(得分:3)

C

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);}

答案 21 :(得分:3)

Scala的

仅方法体54个字符,66个(静态类型)方法声明:

def s(s:String)=(""/:s)((a,b)=>if(s.filter(c=>c==b).size>1)a else a+b)

答案 22 :(得分:3)

VB.NET / LINQ

完整工作声明的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个字符。

(请在回答之前确保您的代码有效。谢谢。)

答案 23 :(得分:3)

红宝石

63个字符。

puts (t=gets.split(//)).map{|i|t.count(i)>1?nil:i}.compact.join

答案 24 :(得分:3)

TCL

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]]

答案 25 :(得分:3)

Javascript 1.8

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('');

答案 26 :(得分:2)

LilyPond,78个字符

z=#(ly:gulp-file"A")#(print(string-delete z(lambda(x)(>(string-count z x)1))))

用法:$ cp input.in A; lilypond this.ly

答案 27 :(得分:2)

sed,41个字符

:;s/((.).*\2.*)\2/\1/;t;s/(.)(.*)\1/\2/;t

用法:$ echo nbHHkRbvnrXbvkn | sed -r ':;s/((.).*\2.*)\2/\1/;t;s/(.)(.*)\1/\2/;t'

gnarf pyon的贡献;)。

答案 28 :(得分:2)

PHP

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;

答案 29 :(得分:2)

C#(53个字符)

其中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());

答案 30 :(得分:2)

Haskell Pointfree

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个字符,但它有点长。

答案 31 :(得分:2)

Shell / Coreutils,37个字符

fold -w1|sort|uniq -u|paste -s -d ''

答案 32 :(得分:1)

的Lua

98 char函数,115 char完整程序

f是以最易读的格式编写的,而g旨在以更简洁的方式重现f

小写fg函数是“详细”,大写FG是“压缩”版本。

JG相同,但声明显示完整程序的必要字符数。

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 removedups.lua nbHHkRvrXbvkn
RrX

答案 33 :(得分:1)

Lua,91个字符

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)

答案 34 :(得分:1)

D2(模板):195 197 199 + 17个字符

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");

答案 35 :(得分:1)

使用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++;}}

并且通过删除变量的类型defs,可以将其降低到105(新的C赢家我认为:P)但是我的编译器正在抛出错误!

你们有什么想法?

答案 36 :(得分:1)

SED /爪哇

如果您不包含命令的调用,则 30 字符或 21 字符的sed版本:

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);}}

答案 37 :(得分:1)

欣快

一个非常详细的语言中的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

答案 38 :(得分:0)

D编程语言版本2,68个字符:

auto f(S)(S s){return array(filter!((a){return s.count(a)<2;})(s));}

答案 39 :(得分:0)

Lua,97个字符

i=...repeat c=i:match("(.).-%1")i=c and i:gsub(c:gsub("(%W)","%%%1"),"")or i until not c print(i)

答案 40 :(得分:0)

F#,非Code-Golf版使用列表:

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

答案 41 :(得分:0)

GW-BASIC - 117个字符

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

答案 42 :(得分:0)

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

答案 43 :(得分:0)

#!/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"

答案 44 :(得分:0)

F#,94个字符

let f(a:string)=new string(Seq.toArray(Seq.filter(fun(c:char)->a.IndexOf c=a.LastIndexOf c)a))
printfn "%s" (f "nbHHkRvrXbvkn")

答案 45 :(得分:0)

Python,50个字符(基于SHiNKiROU 67 char版本)

f=lambda s:''.join([c for c in s if s.count(c)<2])

答案 46 :(得分:0)

ASL:23

args1[;{},,\=/+1=]""z P

ASL是我制作的Golfscript灵感脚本语言。

答案 47 :(得分:-2)

我无法找到原始答案,但本着Jon Skeet的回答:

地带:

RSP

该程序的含义是:从标准输入(R)读取一个字符串,删除所有重复的字符(S),将结果打印到stdout(P)。