30

The challenge: The shortest code, by character count, that detects and removes duplicate characters in a String. Removal includes ALL instances of the duplicated character (so if you find 3 n's, all three have to go), and original character order needs to be preserved.

Example Input 1:
nbHHkRvrXbvkn

Example Output 1:
RrX


Example Input 2:
nbHHkRbvnrXbvkn

Example Output 2:
RrX

(the second example removes letters that occur three times; some solutions have failed to account for this)

(This is based on my other question where I needed the fastest way to do this in C#, but I think it makes good Code Golf across languages.)

Community
  • 1
  • 1
Alex
  • 75,813
  • 86
  • 255
  • 348

48 Answers48

38

LabVIEW 7.1

ONE character and that is the blue constant '1' in the block diagram. I swear, the input was copy and paste ;-)

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

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

Frank Bollack
  • 24,478
  • 5
  • 49
  • 58
  • 5
    hmmm - exactly how large is the resulting vi when saved? ;) – Ankur Goel Feb 10 '10 at 15:53
  • I guess. This is a lot like the "in my imaginary X language, it's only one character, because that's all the language does!" type answers. Sure, no "code"...because it's all in the design of the underlying system. Still, kudos for originality. – Beska Feb 10 '10 at 16:01
  • 1
    The resulting VI is exactly 31.126 Bytes in size. – Frank Bollack Feb 14 '10 at 19:42
26

Perl

21 characters of perl, 31 to invoke, 36 total keystrokes (counting shift and final return):

perl -pe's/$1//gwhile/(.).*\1/'
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • It's customary to post the language and the character count. – Chris Lutz Aug 28 '09 at 06:15
  • (Disclaimer: I'm no Perl guru.) I tested with v5.8.8 and it seems you can remove the space after -pe to save a character. – strager Aug 28 '09 at 21:04
  • There are a few characters we can remove. You are correct about that space. Also, the space after the `while` should be superfluous and the semicolon is also superfluous since it's only one line. However, 35 characters is in _no_ danger of being beaten any time soon. – Chris Lutz Aug 29 '09 at 08:52
  • The apl solution of 23 characters requires that the excess spaces be removed. – William Pursell Aug 31 '09 at 13:41
  • 5
    Damn, I didn't know Perl would let you get away with `s///gwhile`. That's kind of ridiculous. – Chris Lutz Aug 31 '09 at 21:12
  • 1
    `perl -pe'y///cs'` would work, **if** the copied characters were guaranteed to be next to each other. – Brad Gilbert Feb 10 '10 at 15:42
19

Ruby — 61 53 51 56 35

61 chars, the ruler says. (Gives me an idea for another code golf...)

  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 by Nakilon

Nakilon
  • 34,866
  • 14
  • 107
  • 142
Paige Ruten
  • 172,675
  • 36
  • 177
  • 197
  • With the newer version of ruby, you can drop the '.to_s'. I actually like yours better, for a few different reasons. – nilamo Aug 28 '09 at 08:32
18

APL

23 characters:

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

I'm an APL newbie (learned it yesterday), so be kind -- this is certainly not the most efficient way to do it. I'm ashamed I didn't beat Perl by very much.

Then again, maybe it says something when the most natural way for a newbie to solve this problem in APL was still more concise than any other solution in any language so far.

Alec
  • 759
  • 1
  • 5
  • 8
15

Python:

s=raw_input()
print filter(lambda c:s.count(c)<2,s)

This is a complete working program, reading from and writing to the console. The one-liner version can be directly used from the command line

python -c 's=raw_input();print filter(lambda c:s.count(c)<2,s)'
Steve Losh
  • 19,642
  • 2
  • 51
  • 44
recursive
  • 83,943
  • 34
  • 151
  • 241
  • That doesn't seem to work in my version of Python unless i add square brackets around the array constructs - join([...]). – Shawn Chin Aug 28 '09 at 09:13
  • That's a generator expression and was added in Python 2.2. I think it's reasonable to assume everyone who actually uses Python is on that version or higher. – Kenan Banks Aug 28 '09 at 11:27
  • I'm using Python 2.3.4 (RHEL4), and it moans about the above expression - "SyntaxError: invalid syntax". Only in Python 2.4 and above perhaps? – Shawn Chin Aug 28 '09 at 12:33
  • Generator expressions were added in 2.4. Anyway the new version is shorter and doesn't use them. – Steve Losh Aug 28 '09 at 14:24
  • You can just use `input()` to reduce char. And can you please add a char count? – avacariu Aug 30 '10 at 23:16
14

J (16 12 characters)

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

Example:

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

It only needs the parenthesis to be executed tacitly. If put in a verb, the actual code itself would be 14 characters.

There certainly are smarter ways to do this.

EDIT: The smarter way in question:

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

12 characters, only 10 if set in a verb. I still hate the fact that it's going through the list twice, once to count (#/.) and another to return uniques (nub or ~.), but even nubcount, a standard verb in the 'misc' library does it twice.

MPelletier
  • 16,256
  • 15
  • 86
  • 137
  • 2
    Another way to do it in 12 characters is `(]-.-.@~:#])`, with the advantage of only going through the list once. It just copies from the list the `not` of the nubsieve, then removes those elements from the list. – David Apr 20 '10 at 16:43
  • 1
    @David: And more emoticons, too. – Dave Jarvis Aug 31 '10 at 00:33
12

Haskell

There's surely shorter ways to do this in Haskell, but:

Prelude Data.List> let h y=[x|x<-y,(<2).length$filter(==x)y]
Prelude Data.List> h "nbHHkRvrXbvkn"
"RrX"

Ignoring the let, since it's only required for function declarations in GHCi, we have h y=[x|x<-y,(<2).length$filter(==x)y], which is 37 characters (this ties the current "core" Python of "".join(c for c in s if s.count(c)<2), and it's virtually the same code anyway).

If you want to make a whole program out of it,

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

Or we can knock off one character this way:

main=interact(\y->[x|x<-y,(<2).length$filter(==x)y])

$ echo "nbHHkRvrXbvkn" | runghc tmp2.hs
RrX

$ wc -c tmp2.hs
53 tmp2.hs

It operates on all of stdin, not line-by-line, but that seems acceptable IMO.

Community
  • 1
  • 1
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
  • For those interested I've posted a haskell solution in a pointfree style: http://stackoverflow.com/questions/1344352/code-golf-duplicate-character-removal-in-string/2238192#2238192 – Geoff Reedy Feb 10 '10 at 22:59
9

C89 (106 characters)

This one uses a completely different method than my original answer. Interestingly, after writing it and then looking at another answer, I saw the methods were very similar. Credits to caf for coming up with this method before me.

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

On one line, it's 58+48 = 106 bytes.

C89 (173 characters)

This was my original answer. As said in the comments, it doesn't work too well...

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

On two lines, it's 17+1+78+77 = 173 bytes.

Community
  • 1
  • 1
strager
  • 88,763
  • 26
  • 134
  • 176
  • 1
    You're calling `realloc` and `memchr` without compatible declarations in scope. – caf Aug 28 '09 at 06:06
  • What language? – Svish Aug 28 '09 at 07:25
  • 1
    @Svish - C. Perhaps you should get out more. I don't know Ruby or C# but I can more or less recognize them when I see them. – Chris Lutz Aug 28 '09 at 07:46
  • @caf: Not true. Calling realloc() on NULL (b is initialized from 0) is fine, and acts like malloc(). – unwind Aug 28 '09 at 08:05
  • @unwind - He's saying that they're not declared, i.e. no `extern void *realloc(void *ptr, size_t len);`. Of course, all you really need is `void *realloc();`, but they _do_ technically need to be declared since they don't return `int`. – Chris Lutz Aug 28 '09 at 08:17
  • int is just casted to char *, which I take for granted. Yes, it's non-standard, but the necessary #include's brings up the file size too much. Maybe I can trim it down even more or even not use memchr. – strager Aug 28 '09 at 20:37
  • It's not cast, because the compiler doesn't even know that those functions are returning `void *` (eg imagine what would happen under an ABI that says pointer and scalar return values are returned in two different registers?) – caf Aug 29 '09 at 01:19
  • On your new one - you're assuming that `EOF` is negative (that's not actually guaranteed - it could be a positive integer outside the range of `unsigned char`). By the way, the definition of `EOF` is the only reason our solutions need `stdio.h` - the implicit declarations of `getchar()` and `putchar()` are compatible (unlike `memchr` and `realloc`). And remember that objects with static storage duration are guaranteed initialised to zero. (I'm also not completely comfortable that our solutions fail to `return` a value from `main`). – caf Aug 29 '09 at 01:25
  • @strager - You don't strictly need the headers. You know the definitions, you could just say `void*realloc();` and it would be declared. – Chris Lutz Aug 29 '09 at 08:50
  • @caf, I see your point about ABI's and such. Also, everywhere I look I see EOF must be a negative integer. @Lutz, I see. – strager Aug 29 '09 at 15:57
  • Sorry, you're right that EOF must be a negative integral expression. – caf Aug 30 '09 at 13:42
8

C#

65 Characters:

new String(h.Where(x=>h.IndexOf(x)==h.LastIndexOf(x)).ToArray());

67 Characters with reassignment:

h=new String(h.Where(x=>h.IndexOf(x)==h.LastIndexOf(x)).ToArray());
Svish
  • 152,914
  • 173
  • 462
  • 620
Dykam
  • 10,190
  • 4
  • 27
  • 32
7

C#

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

71 characters

Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
  • Found out it could actually be even a few chars less with your method, changing cs to c and removing whitespace. Then it becomes 66 chars. Though I've found a method one char less. – Dykam Aug 28 '09 at 06:58
  • "input" is string, so it doesn't have GroupBy method. You should add call to "ToCharArray" method. – Kamarey Aug 28 '09 at 10:02
  • 5
    System.String implements IEnumerable, so it has the GroupBy method. The IDE makes an exception for the extension methods on string and doesn't show them, but they compile and run just fine. – Bryan Watts Aug 28 '09 at 14:05
  • Bryan, that's only the case for Visual Studio, as I did see them appear in #D. – Dykam Aug 30 '09 at 17:02
  • Fair enough, sometimes you forget there are alternatives :-) – Bryan Watts Aug 30 '09 at 17:19
6

PHP (136 characters)

<?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.

Community
  • 1
  • 1
strager
  • 88,763
  • 26
  • 134
  • 176
6

another APL solution

As a dynamic function (18 charachters)

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

line assuming that input is in variable x (16 characters):

(1+=/¨(x∘∊¨x))/x
davrieb
  • 559
  • 2
  • 7
5

VB.NET

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

Granted, VB is not the optimal language to try to save characters, but the line comes out to 98 characters.

Svish
  • 152,914
  • 173
  • 462
  • 620
BP.
  • 10,033
  • 4
  • 34
  • 53
  • I'm no VB expert, but it looks like there's a bunch of Whitespace in your answer, Does vb require all that whitespace? – SingleNegationElimination Aug 28 '09 at 03:04
  • If it is anything like VB6 then it forces the whitespace on you. – graham.reeds Aug 28 '09 at 08:07
  • Yeah, the IDE adds the spaces for you. – BP. Aug 28 '09 at 15:58
  • No, most whitespaces are absolutely useless here. Being an advanced IDE, VS inserts them for you. But in a code golf they’re shouldn’t count. – Konrad Rudolph Aug 31 '09 at 15:50
  • Also, you can replace `IIf` by plain `If`. Better code, less characters. And just porting the C# solution from below would have been shorter still. – Konrad Rudolph Aug 31 '09 at 16:25
  • 1
    Yes, it will work without the spaces even if VS automatically inserts them. And using `If` instead of `IIf` makes it better. You can also skip converting c to string. And why not replace with `""` instead of `Nothing`... All of these will result in this 75 char code: `For Each c In s:s=If(s.LastIndexOf(c)<>s.IndexOf(c),s.Replace(c,""),s):Next` – awe Sep 01 '09 at 11:55
  • You can turn off the VB Specific "Pretty listing (reformatting of code)". – AMissico Nov 29 '09 at 20:16
5

PowerShell

61 characters. Where $s="nbHHkRvrXbvkn" and $a is the result.

$h=@{}
($c=[char[]]$s)|%{$h[$_]++}
$c|%{if($h[$_]-eq1){$a+=$_}}

Fully functioning parameterized script:

param($s)
$h=@{}
($c=[char[]]$s)|%{$h[$_]++}
$c|%{if($h[$_]-eq1){$a+=$_}}
$a
Eric Schoonover
  • 47,184
  • 49
  • 157
  • 202
  • I managed to get it to 58. I can't believe I just spent 20 minutes on this. [Char[]]$s|%{if($s -clike"*$_*$_*"){$s=$s -creplace$_,''}} – Josh Mar 11 '10 at 07:01
5

C: 83 89 93 99 101 characters

  • O(n2) time.
  • Limited to 999 characters.
  • Only works in 32-bit mode (due to not #include-ing <stdio.h> (costs 18 chars) making the return type of gets being interpreted as an int and chopping off half of the address bits).
  • Shows a friendly "warning: this program uses gets(), which is unsafe." on Macs.

.

main(){char s[999],*c=gets(s);for(;*c;c++)strchr(s,*c)-strrchr(s,*c)||putchar(*c);}

(and this similar 82-chars version takes input via the command line:

main(char*c,char**S){for(c=*++S;*c;c++)strchr(*S,*c)-strrchr(*S,*c)||putchar(*c);}

)

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
5

Golfscript(sym) - 15

  .`{\{=}+,,(!}+,
+-------------------------------------------------------------------------+
||    |    |    |    |    |    |    |    |    |    |    |    |    |    |  |
|0         10        20        30        40        50        60        70 |
|                                                                         |
+-------------------------------------------------------------------------+
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
4

Haskell

(just knocking a few characters off Mark Rushakoff's effort, I'd rather it was posted as a comment on his)

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

which is better Haskell idiom but maybe harder to follow for non-Haskellers than this:

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

Edit to add an explanation for hiena and others:

I'll assume you understand Mark's version, so I'll just cover the change. Mark's expression:

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

filters y to get the list of elements that == x, finds the length of that list and makes sure it's less than two. (in fact it must be length one, but ==1 is longer than <2 ) My version:

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

does the same filter, then puts the resulting list into a list as the only element. Now the arrow (meant to look like set inclusion!) says "for every element of the RHS list in turn, call that element [z]". [z] is the list containing the single element z, so the element "filter(==x)y" can only be called "[z]" if it contains exactly one element. Otherwise it gets discarded and is never used as a value of z. So the z's (which are returned on the left of the | in the list comprehension) are exactly the x's that make the filter return a list of length one.

That was my second version, my first version returns x instead of z - because they're the same anyway - and renames z to _ which is the Haskell symbol for "this value isn't going to be used so I'm not going to complicate my code by giving it a name".

yairchu
  • 23,680
  • 7
  • 69
  • 109
  • could you explain your solution? I'm having trouble understanding :S – hiena Aug 31 '09 at 14:00
  • For those interested I've posted a haskell solution in a pointfree style: http://stackoverflow.com/questions/1344352/code-golf-duplicate-character-removal-in-string/2238192#2238192 – Geoff Reedy Feb 10 '10 at 23:00
3

Javascript 1.8

s.split('').filter(function (o,i,a) a.filter(function(p) o===p).length <2 ).join('');

or alternately- similar to the python example:

[s[c] for (c in s) if (s.split("").filter(function(p) s[c]===p).length <2)].join('');
Svish
  • 152,914
  • 173
  • 462
  • 620
Breton
  • 15,401
  • 3
  • 59
  • 76
3

TCL

123 chars. It might be possible to get it shorter, but this is good enough for me.

proc h {i {r {}}} {foreach c [split $i {}] {if {[llength [split $i $c]]==2} {set r $r$c}}
return $r}
puts [h [gets stdin]]
Svish
  • 152,914
  • 173
  • 462
  • 620
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
3

Ruby

63 chars.

puts (t=gets.split(//)).map{|i|t.count(i)>1?nil:i}.compact.join
nilamo
  • 1,932
  • 13
  • 22
3

VB.NET / LINQ

96 characters for complete working statement

Dim p=New String((From c In"nbHHkRvrXbvkn"Group c By c Into i=Count Where i=1 Select c).ToArray)

Complete working statement, with original string and the VB Specific "Pretty listing (reformatting of code" turned off, at 96 characters, non-working statement without original string at 84 characters.

(Please make sure your code works before answering. Thank you.)

AMissico
  • 21,470
  • 7
  • 78
  • 106
3

Scala

54 chars for the method body only, 66 with (statically typed) method declaration:

def s(s:String)=(""/:s)((a,b)=>if(s.filter(c=>c==b).size>1)a else a+b)
Svish
  • 152,914
  • 173
  • 462
  • 620
Fabian Steeg
  • 44,988
  • 7
  • 85
  • 112
3

C

Full program in C, 141 bytes (counting newlines).

#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);}
Svish
  • 152,914
  • 173
  • 462
  • 620
caf
  • 233,326
  • 40
  • 323
  • 462
3

C

(1st version: 112 characters; 2nd version: 107 characters)

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

That's

/* #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; */
}

Because getchar() returns int and putchar accepts int, the #include can 'safely' be removed. Without the include, EOF is not defined, so I used -1 instead (and gained a char). This program only works as intended for inputs with less than 100000 characters!

Version 2, with thanks to strager 107 characters

#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
pmg
  • 106,608
  • 13
  • 126
  • 198
  • Some suggestions: You can save a byte by putting c as parameters to main. You can also use k[o[c]]-1?0:putchar(o[c]); in your second loop to save a few bytes as well. You can maybe save bytes (in source size and memory) using 9's instead of 0's for your big array. – strager Aug 29 '09 at 20:35
3

Javascript 1.6

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

Shorter than the previously posted Javascript 1.8 solution (71 chars vs 85)

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
adamJLev
  • 13,713
  • 11
  • 60
  • 65
3

Assembler

Tested with WinXP DOS box (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

Assembles to 53 bytes. Reads standard input and writes results to standard output, eg:

 programname < input > output
Skizz
  • 69,698
  • 10
  • 71
  • 108
2

PHP

118 characters actual code (plus 6 characters for the PHP block tag):

<?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;
Gumbo
  • 643,351
  • 109
  • 780
  • 844
2

C# (53 Characters)

Where s is your input string:

new string(s.Where(c=>s.Count(h=>h==c)<2).ToArray());

Or 59 with re-assignment:

var a=new string(s.Where(c=>s.Count(h=>h==c)<2).ToArray());
BenAlabaster
  • 39,070
  • 21
  • 110
  • 151
2

Haskell Pointfree

import Data.List
import Control.Monad
import Control.Arrow
main=interact$liftM2(\\)nub$ap(\\)nub

The whole program is 97 characters, but the real meat is just 23 characters. The rest is just imports and bringing the function into the IO monad. In ghci with the modules loaded it's just

(liftM2(\\)nub$ap(\\)nub) "nbHHkRvrXbvkn"

In even more ridiculous pointfree style (pointless style?):

main=interact$liftM2 ap liftM2 ap(\\)nub

It's a bit longer though at 26 chars for the function itself.

Geoff Reedy
  • 34,891
  • 3
  • 56
  • 79
2

Shell/Coreutils, 37 Characters

fold -w1|sort|uniq -u|paste -s -d ''
Community
  • 1
  • 1
Hasturkun
  • 35,395
  • 6
  • 71
  • 104
2

sed, 41 chars

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

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

With contributions by gnarfpyon ;).

Community
  • 1
  • 1
KirarinSnow
  • 1,062
  • 2
  • 9
  • 22
2

LilyPond, 78 chars

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

Usage: $ cp input.in A; lilypond this.ly

KirarinSnow
  • 1,062
  • 2
  • 9
  • 22
1

Euphoria

165 characters from a pretty verbose language.

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
Matt Lewis
  • 531
  • 1
  • 3
  • 6
1

sed/Java

A sed version with 30 characters, or 21 characters if you don't include the invocation of the command:

sed -r ':_;s/(.)(.*)\1/\2/;t_'

A java version using the same idea (should all be written in one line) which is 157 characters:

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);}}
Community
  • 1
  • 1
IRBMe
  • 4,335
  • 1
  • 21
  • 22
  • 1
    The sed doesn't work. It doesn't remove a character if it appears an odd number of times. Also, looping can be done with just `:; ...; t;` – KirarinSnow Feb 11 '10 at 21:43
1

Lua

98 char function, 115 char full program

f was written in the most readable format, and g aimed to reproduce f exactly but in a more terse manner.

Lowercase f and g functions are "verbose," and uppercase F and G are the "compressed" versions.

J is identical to G, but it is declared to show the necessary character count for a full program.

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

Output:

$ lua removedups.lua nbHHkRvrXbvkn
RrX
Community
  • 1
  • 1
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
  • Lovely, with the ruler and everything. +1 – Alex Sep 16 '09 at 01:49
  • Function F calls function f() instead of F(). Function G calls function g() instead of G(). Implementation has problems when string contains pattern magic characters `().%+-*?[]^$`. Try escaping matching string with `h:gsub('(%W)','%%%1')`. – gwell Feb 10 '10 at 22:52
  • How about this 96 characters LUA code: `s=arg[1];r='';for i in s:gmatch('.') do if s:match(i..'.*'..i)==nil then r=r..i end end;print(r)` – fogo Feb 12 '10 at 14:19
1

using C - 118 Characters

I think this answer is good as it will work for any string length.

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

and by removing the type defs of the variables, can get it down to 105 (new C winner i think :P) but my compiler is throwing errors with that!

What do you guys think?

jme
  • 311
  • 4
  • 19
  • I can reduce it to 111 using `i=0;main(s,A,j,c,d){char**a=A;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++;}}`. – kennytm Feb 10 '10 at 14:49
1

D2 (templates): 195 197 199 + 17 characters

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

Expanded:

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");
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
1

Lua, 91 characters

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)
Mud
  • 28,277
  • 11
  • 59
  • 92
0

Lua, 97 Characters

i=...repeat c=i:match("(.).-%1")i=c and i:gsub(c:gsub("(%W)","%%%1"),"")or i until not c print(i)
Community
  • 1
  • 1
gwell
  • 2,695
  • 20
  • 20
0

The D programming language version 2, 68 characters:

auto f(S)(S s){return array(filter!((a){return s.count(a)<2;})(s));}
dsimcha
  • 67,514
  • 53
  • 213
  • 334
0

F#, Non-Code-Golf version using lists:

16 ilnes using lists:

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 characters - More terse version without lists:

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
Igor Zevaka
  • 74,528
  • 26
  • 112
  • 128
0

GW-BASIC - 117 chars

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
Carlos Gutiérrez
  • 13,972
  • 5
  • 37
  • 47
0

OCaml, 93 characters (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
bltxd
  • 8,825
  • 5
  • 30
  • 44
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"
Ming-Tang
  • 17,410
  • 8
  • 38
  • 76
0

F#, 94 chars

let f(a:string)=new string(Seq.toArray(Seq.filter(fun(c:char)->a.IndexOf c=a.LastIndexOf c)a))
printfn "%s" (f "nbHHkRvrXbvkn")
Community
  • 1
  • 1
Ming-Tang
  • 17,410
  • 8
  • 38
  • 76
0

Python, 50 chars (based on SHiNKiROU 67 char version)

f=lambda s:''.join([c for c in s if s.count(c)<2])
Andrea Ambu
  • 38,188
  • 14
  • 54
  • 77
0

ASL: 23

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

ASL is a Golfscript inspired scripting language I made.

Labbekak
  • 517
  • 3
  • 14
-2

I couldn't find the original answer, but in the spirit of a Jon Skeet answer:

Strip:

RSP

The meaning of this program is: Read a string from standard input (R), Strip all duplicate characters (S), Print the result to stdout (P).

Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
  • 3
    Martin _did_ do it in one character - but he then took on the harder challenge of writing it as a full program instead of just a function. – Chris Lutz Aug 28 '09 at 06:23
  • 6
    -1 for not being Jon Skeet and I wish I could add another -1 for annoying fanboyism. – Eric Aug 28 '09 at 08:03
  • 3
    How about -1 for having fun while you're at it? – Chris Lutz Aug 28 '09 at 08:05
  • 4
    Ha ha, yes, let's reuse Jon Skeet's jokes. It was amusing when he did it, but now it is just tired. – Eric Aug 28 '09 at 08:13
  • 1
    I'm not saying it's a paragon of comedic genius, but it made me chuckle. If you're tired of it, that's fine - just don't read it. – Chris Lutz Aug 28 '09 at 08:18