Type uniqchars!

41

1

Given a string consisting of printable ASCII chars, produce an output consisting of its unique chars in the original order. In other words, the output is the same as the input except that a char is removed if it has appeared previously.

No built-ins for finding unique elements in an array can be used (for example, MATLAB has a unique function that does that). The idea is to do it manually.

Further details:

  • Either functions or programs are allowed.
  • Input and output can be in the form of function arguments, stdin/stdout (even for functions), or a mix of those.
  • If stdin or stdout are used, a string is understood as just the sequence of chars. If function arguments are used, the sequence of chars may need to be enclosed in quotation marks or equivalent symbols that the programming language of choice uses for defining strings.
  • The output should be a string containing only the unique characters of the input. So no extra linebreaks, spaces etc. The only exception is: if the output is displayed in stdout, most displaying functions add a trailing \n (to separate the string from what will come next). So one trailing \n is acceptable in stdout.
  • If possible, post a link to an online interpreter/compiler so that others can try your code.

This is code golf, so shortest code in bytes wins.

Some examples, assuming stdin and stdout:

  1. Input string:

    Type unique chars!
    

    Output string:

    Type uniqchars!
    
  2. Input string

    "I think it's dark and it looks like rain", you said
    

    Output string

    "I think'sdarloe,yu
    
  3. Input string

    3.1415926535897932384626433832795
    

    Output string

    3.14592687
    

Luis Mendo

Posted 2015-10-04T14:46:30.477

Reputation: 87 464

5Just to double check: Does the no builtins rule mean that set objects are disallowed? – Sp3000 – 2015-10-04T14:51:36.113

@Sp3000 Set objects are allowed. Just don't use a function or method (if it exists) that gives you its unique elements. And input/output should be strings, not set tobjects – Luis Mendo – 2015-10-04T14:54:07.870

@Sp3000 Do you think it would make it more interesting to reduce byte count by half if no set functions are used? Or better not change the rules once the challenge has been set? – Luis Mendo – 2015-10-04T15:08:01.550

5I think only my answer uses sets currently, and I wouldn't mind if you changed it. However, I'm not really sure a bonus like that would change much, e.g. I doubt CJam would be doable in < 6 bytes without sets. Also, I'm not sure where the line is between a builtin which finds unique elements, and constructing a set from a number of elements... – Sp3000 – 2015-10-04T15:13:11.510

1@Sp3000 Yes, it's a blurred border. I hadn't anticipated set functions. I think I'll leave the challenge as it is now – Luis Mendo – 2015-10-04T15:16:08.020

@ThomasKwa I agree with you. In fact, when an interpreter prints a string to the screen, there's usually an implicit \n printed at the end even if the string doesn't have it. I've notified J F – Luis Mendo – 2015-10-05T09:53:10.367

Is it allowed for the input data structure to have a different type from the output data structure, if they both are valid representations of strings of characters? – CR Drost – 2015-10-06T18:07:42.163

I guess if they both represent strings that's fine. But I'm confused: how can they represent strings without actually being string data type? – Luis Mendo – 2015-10-06T20:34:27.110

@LuisMendo: I mean the easiest example might be JavaScript where "abc".split("") is a data structure which represents a string without actually being one. (Some of the below answers might be able to use this to shave 10 or more bytes off!) The case that I am talking about is a lot more convoluted and appears below in my Haskell answer. – CR Drost – 2015-10-07T00:44:29.173

@Sp3000 I totally missed than answer. Thanks for the heads-up! – Luis Mendo – 2015-10-09T10:10:07.893

1-byte cheating Jelly solution: Q. – Erik the Outgolfer – 2016-09-28T14:46:30.740

@EriktheGolfer Doubly cheating – Luis Mendo – 2016-09-28T14:51:41.433

@EriktheGolfer Because the language postdates the challenge and because builtin is not allowed – Luis Mendo – 2016-09-28T14:53:25.743

@LuisMendo Non-competing is not always cheating. Non-competing does not compete at all, so what sort of cheating is it? – Erik the Outgolfer – 2016-09-28T14:54:01.443

Ah, finally a use for the pangram "Cwm fjord bank glyphs vext quiz." Or for my favorite word, Abcdefghijklmnopqrstuvwxyz

– Draco18s no longer trusts SE – 2017-05-17T15:45:21.227

-1 Disallowing built-ins serves no purpose other than making interesting answers. This is code-golf, not popularity contests. – MilkyWay90 – 2019-04-06T02:26:39.920

Answers

13

GolfScript, 2 bytes

.&

or, alternatively:

.|

I posted this a while ago in the Tips for golfing in GolfScript thread. It works by duplicating the input string (which is put on the stack automatically by the GolfScript interpreter, and which behaves in most ways like an array of characters) and then taking the set intersection (&) or union (|) of it with itself. Applying a set operator to an array (or string) collapses any duplicates, but preserves the order of the elements.

Ilmari Karonen

Posted 2015-10-04T14:46:30.477

Reputation: 19 513

23

CJam, 3 bytes

qL|

Setwise or of the input with an empty list. CJam set operations preserve element order.

Try it online

Sp3000

Posted 2015-10-04T14:46:30.477

Reputation: 58 729

I'm assuming this is valid since sets are allowed, but I'm not sure... – Sp3000 – 2015-10-04T14:58:10.497

Very clever! I knew CJam would be one of the best, but I didn't expect just 3 bytes! – Luis Mendo – 2015-10-04T14:59:11.177

19

C# 6, 18 + 67 = 85 bytes

Requires this using statement:

using System.Linq;

The actual method:

string U(string s)=>string.Concat(s.Where((x,i)=>s.IndexOf(x)==i));

This method saves some chars by defining the function as a lambda, which is supported in C# 6. This is how it would look in C# pre-6 (but ungolfed):

string Unique(string input)
{
    return string.Concat(input.Where((x, i) => input.IndexOf(x) == i));
}

How it works: I call the Where method on the string with a lambda with two arguments: x representing the current element, i representing the index of that element. IndexOf always returns the first index of the char passed to it, so if i is not equal to the first index of x, it's a duplicate char and mustn't be included.

ProgramFOX

Posted 2015-10-04T14:46:30.477

Reputation: 8 017

3I honestly wouldn't have expected C# to be this short. Excellent job! – Alex A. – 2015-10-04T17:40:18.707

Uhm. I think you should submit a complete program (with static void Main etc.). – Timwi – 2015-10-05T10:49:46.143

3@Timwi This challenge states "Either functions or programs are allowed." – hvd – 2015-10-05T14:22:40.250

C# allows for a shorter approach, also using LINQ. I've posted a competing answer. :) – hvd – 2015-10-05T14:37:09.713

@hvd Nice one! +1 – ProgramFOX – 2015-10-05T15:19:19.573

14

Retina, 14 bytes

+`((.).*)\2
$1

Each line should go in its own separate file, or you can use the -s flag to read from one file.

To explain it, we'll use this longer but simpler version:

+`(.)(.*)\1
$1$2

The first line is the regex to match with (+` is the configuration string that keeps running until all replacements have been made). The regex looks for a character (we'll call it C), followed by zero or more arbitrary characters, followed by C. The parentheses denote capturing groups, so we replace the match with C ($1) and the characters in between ($2), removing the duplicate of C.

For example, if the input string was unique, the first run would match uniqu, with u and niq as $1 and $2, respectively. It would then replace the matched substring in the original input with uniq, giving uniqe.

NinjaBearMonkey

Posted 2015-10-04T14:46:30.477

Reputation: 9 925

3I was looking for a regex to do this; I didn't realize it was so short! +1 – ETHproductions – 2015-10-04T22:54:01.230

13

Perl, 21 (20 bytes + -p)

s/./!$h{$&}++&&$&/eg

Usage:

perl -pe 's/./!$h{$&}++&&$&/eg' <<< 'Type unique chars!'
Type uniqchars!

Dom Hastings

Posted 2015-10-04T14:46:30.477

Reputation: 16 415

1You could save 1 byte negating $h{$&} and using a logic AND instead of a ternary operator: s/./!$h{$&}++&&$&/eg – kos – 2015-10-05T12:55:12.513

@kos if you'd asked me, I'd have told you that I 100% tried this and ended up with 1s in the output, but it doesn't! Thank you, updating! – Dom Hastings – 2015-10-05T15:51:25.280

1Upvoted already :) I think you tried s/./$h{$&}++||$&/eg (I fell for that as well at first). Shame because that would have been another saved byte. – kos – 2015-10-05T16:03:29.480

11

Macaroni 0.0.2, 233 bytes

set i read set f "" print map index i k v return label k set x _ set _ slice " " length index f e 1 1 set f concat f wrap x return label e set _ slice " " add _ multiply -1 x 1 1 return label v set _ unwrap slice i _ add 1 _ 1 return
  • create "anti-golfing" language: check
  • golf it anyway: check

This is a full program, which inputs from STDIN and outputs on STDOUT.

Wrapped version, for aesthetic value:

set i read set f "" print map index i k v return label k set x _ set _ slice "
" length index f e 1 1 set f concat f wrap x return label e set _ slice " " add
_ multiply -1 x 1 1 return label v set _ unwrap slice i _ add 1 _ 1 return

And a heavily "commented" and ungolfed version (there are no comments in Macaroni, so I just use bare string literals):

set input read                  "read line from STDIN, store in 'input' var"
set found ""                    "we need this for 'keep' below"
print map index input keep val  "find indeces to 'keep', map to values, print"
return

label keep
    "we're trying to determine which indeces in the string to keep. the special
     '_' variable is the current element in question, and it's also the value
     to be 'returned' (if the '_' variable is '0' or empty array after this
     label returns, the index of the element is *not* included in the output
     array; otherwise, it is"
    set x _ set _ slice
        " "
        length index found exists
        1
        1
    "now we're using 'index' again to determine whether our '_' value exists in
     the 'found' array, which is the list of letters already found. then we
     have to apply a boolean NOT, because we only want to keep values that do
     NOT exist in the 'found' array. we can 'invert' a boolean stored as an
     integer number 'b' (hence, 'length') with 'slice(' ', b, 1, 1)'--this is
     equivalent to ' '[0:1], i.e. a single-character string which is truthy, if
     'b' was falsy; otherwise, it results in an empty string if 'b' was truthy,
     which is falsy"
    set found concat found wrap x  "add the letter to the 'found' array"
return

label exists
    set _ slice
        " "
        add _ multiply -1 x
        1
        1
    "commentary on how this works: since 0 is falsy and every other number is
     truthy, we can simply subtract two values to determine whether they are
     *un*equal. then we apply a boolean NOT with the method described above"
return

label val
    set _ unwrap slice input _ add 1 _ 1  "basically 'input[_]'"
return

(This is the first real Macaroni program (that actually does something)! \o/)

Doorknob

Posted 2015-10-04T14:46:30.477

Reputation: 68 138

5• give the language a funny and appropriate name: check – Luis Mendo – 2015-10-04T15:32:36.820

11

JavaScript ES7, 37 33 25 bytes

Pretty simple approach using ES6 Set and ES7 Array comprehensions spread operator:

s=>[...new Set(s)].join``

22 bytes less than the indexOf approach. Worked on a handful of test cases.

azz

Posted 2015-10-04T14:46:30.477

Reputation: 211

The spaces around for's expression are not necessary and you could make it anonymous function as some other solutions did: s=>[for(c of Set(s))c].join\``. (Pale update: not 100% sure, but the new keyword seems also unnecessary.) – manatwork – 2015-10-05T10:36:17.247

Wasn't sure of the rules with anon functions, and good catch on the space. – azz – 2015-10-05T10:37:47.813

Transpiled code without new resulted in Uncaught TypeError: Constructor Set requires 'new' in Google Chrome. – azz – 2015-10-05T10:43:10.837

Please excuse my ignorance but at what point does this filter unique values? It looks like it just converts a string to a set to an array then joins the values resulting in the original string again. – Patrick Roberts – 2015-10-05T14:17:25.810

@PatrickRoberts it's the conversion to a set. A set by definition has no dupluicates – edc65 – 2015-10-05T14:32:01.950

But are we sure that the conversion to Set mantains the original order? – edc65 – 2015-10-05T14:32:44.413

Answering myself: yes http://www.2ality.com/2015/01/es6-maps-sets.html. And this can be made even shorter: s=>[...new Set(s)].join" or (tested in Firefox) s=>[...Set(s)].join" (21 bytes)

– edc65 – 2015-10-05T14:40:41.943

@edc65 Not sure why I originally went for array comprehension over the spread operator, when I use the latter far more than the former. Good catch. – azz – 2015-10-06T01:15:43.570

8

C# 6 - 18+46=64

using System.Linq;

and then

string f(string s)=>string.Concat(s.Union(s));

The Enumerable.Union extension method specifies that elements are returned in the original order:

When the object returned by this method is enumerated, Union enumerates first and second in that order and yields each element that has not already been yielded.

Set operations that aren't specifically intended to find unique values appear to be allowed judging by the other answers.

hvd

Posted 2015-10-04T14:46:30.477

Reputation: 3 664

Nice one, I was thinking of string u(string s)=>String.Join("",s.Distinct()); but that's a little bit longer. – germi – 2015-10-07T12:41:24.647

@germi Thanks. There has been an answer using Distinct() already, but it's deleted because Distinct() is disallowed in this challenge, as it's a method specifically intended to find unique values. – hvd – 2015-10-07T12:43:50.387

Ah right... overlooked that bit ;) – germi – 2015-10-07T12:47:07.983

Is s => string.Concat(s.Union(s)) valid? That would be the delegate passed to a Func<string, string> as an argument. – Tyler StandishMan – 2016-09-28T03:17:17.037

@TylerStandishMan If that's valid, I would expect more people to make use of it, and I haven't seen it before, so I don't think it is. But maybe it should be valid -- this seems like something worth checking on Meta if you're interested. – hvd – 2016-09-28T05:02:30.883

Thanks. http://codegolf.stackexchange.com/a/84285/39227 is the one place I recall seeing it, and I asked there too lol. I'll check meta

– Tyler StandishMan – 2016-09-28T10:53:19.770

7

JavaScript ES6, 47 bytes

f=s=>s.replace(/./g,(e,i)=>s.indexOf(e)<i?'':e)

The test below works on all browsers.

f=function(s){
  return s.replace(/./g,function(e,i){
    return s.indexOf(e)<i?'':e
  })
}

run=function(){document.getElementById('output').innerHTML=f(document.getElementById('input').value)};document.getElementById('run').onclick=run;run()
<input type="text" id="input" value="Type unique chars!" /><button id="run">Run</button><br />
<pre id="output"></pre>

NinjaBearMonkey

Posted 2015-10-04T14:46:30.477

Reputation: 9 925

What does the <i?'':e part do? – DanTheMan – 2015-10-07T01:50:52.623

1It's a ternary operator. If the first instance of a character e is before the current index i, it returns an empty string, thus getting rid of the character. If that is the first instance, it simply returns e and no changes are made. – NinjaBearMonkey – 2015-10-07T03:03:39.980

7

MATLAB, 23

 @(n)union(n,n,'stable')

Does the "set union" of the input string with itself, using the 'stable' method which does not sort, and then prints.

This works because union returns only non-duplicate values after the merge. So essentially if you union the string with itself, it first produces a string like Type unique chars!Type unique chars!, and then removes all duplicates without sorting.

No need for unique :)

Tom Carpenter

Posted 2015-10-04T14:46:30.477

Reputation: 3 990

unique not allowed, sorry! It's in the challange definition – Luis Mendo – 2015-10-04T15:28:53.807

Missed that, never mind. – Tom Carpenter – 2015-10-04T15:31:26.587

Following Sp3000's answer, may I suggest setdiff with the 'stable' option? – Luis Mendo – 2015-10-04T15:39:15.653

@LuisMendo didn't help. But I found an alternative the unique which with an extra byte achieves the same thing :) – Tom Carpenter – 2015-10-04T16:08:11.637

If you don't mind it saying ans= when it prints out, the disp() can also be removed saving another 6 characters. – Tom Carpenter – 2015-10-04T16:10:47.013

1Nice! And yes, you can remove disp because then you have a function that returns a string , which is allowed – Luis Mendo – 2015-10-04T16:20:11.393

1You can also use intersect with 'stable' to achieve the same effect too. I was going to write that, but given this answer, it's no longer original lol. – rayryeng - Reinstate Monica – 2015-10-04T17:24:05.133

7

Beam, 23 18 bytes

v<H
vs)
rS
g@S
>u^

enter image description here

Try it online!

MickyT

Posted 2015-10-04T14:46:30.477

Reputation: 11 735

7

><>, 16 bytes

i:0(?;:::1g?!o1p

><> doesn't have strings, so we make use of the codebox. Due to the toroidal nature of ><>, the following runs in a loop:

i         Read a char
:0(?;     Halt if EOF
:::       Push three copies of the char
1g        Get the value at (char, 1), which is 0 by default
?!o       Print the char if the value was nonzero
1p        Set the value at (char, 1) to char

Note that this uses the fact that the input only contains printable ASCII, as this would not work if ASCII 0 was present.

Sp3000

Posted 2015-10-04T14:46:30.477

Reputation: 58 729

1.......this is brilliant. I wish I had thought of this. I'll include a Befunge version of this in my answer, but not as the primary. EDIT: On second thought, this wouldn't work because Befunge doesn't have an infinite code space. Dangit! – El'endia Starman – 2015-10-05T05:52:26.053

@El'endiaStarman I think the Beam answer also does the same thing, so unfortunately I can't say I was first :P

– Sp3000 – 2015-10-05T05:53:22.333

Ahh, yeah, I think you're right. Your explanation is clearer though. – El'endia Starman – 2015-10-05T06:03:33.103

5

Element, 22 19 18 bytes

_'{"(3:~'![2:`];'}

Example input/output: hello world -> helo wrd

This works by simply processing the string one character at a time and keeping track which ones it has seen before.

_'{"(3:~'![2:`];'}
_                        input line
 '                       use as conditional
  {              }       WHILE loop
   "                     retrieve string back from control (c-) stack
    (                    split to get the first character of (remaining) string
     3:                  a total of three copies of that character
       ~                 retrieve character's hash value
        '                put on c-stack
         !               negate, gives true if undef/empty string
          [   ]          FOR loop
           2:`           duplicate and output
               ;         store character into itself
                '        put remaining string on c-stack as looping condition

PhiNotPi

Posted 2015-10-04T14:46:30.477

Reputation: 26 739

5

Python 2, 42 bytes

Uses a couple anonymous functions and reduce.

lambda s:reduce(lambda x,y:x+y[y in x:],s)

Try it online

mbomb007

Posted 2015-10-04T14:46:30.477

Reputation: 21 944

4

Python 3, 44

r=''
for c in input():r+=c[c in r:]
print(r)

Builds the output string r character by character, including the character c from the input only if we haven't seen it already.

Python 2 would be 47, losing 4 chars with raw_input and saving 1 on not needing parers for print.

xnor

Posted 2015-10-04T14:46:30.477

Reputation: 115 687

The consensus now seems to be that you can use input in Python 2, so you can make yours a byte shorter. – mbomb007 – 2016-09-28T13:24:52.030

4

APL, 3

∊∪/

This applies union (∪) between each element of the vector, obtaining an iteration that has the effect of removing duplicates.

Test it on tryapl.org

Old One:

~⍨\

This uses ~ (with reversed arguments, using ⍨) applied between each element of the argument. The result is that for each element, if it's already in the list, it gets erased.

Moris Zucca

Posted 2015-10-04T14:46:30.477

Reputation: 1 519

Nitpicking: "And input/output should be strings" says Luis. "Unione reduce" returns a nested array, not a string. O:-) – lstefano – 2016-06-28T11:28:28.840

You're right, adding a ∊ at the beginning to correct. – Moris Zucca – 2016-06-28T14:42:03.500

3

Julia, 45 42 bytes

s->(N="";[i∈N?N:N=join([N,i])for i=s];N)

Old version:

s->(N={};for i=s i∈N||(N=[N,i])end;join(N))

Code builds the new string by appending new characters onto it, then joins them together to a proper string at the end. New version saves some characters by iterating via array comprehension. Also saves a byte by using ?: rather than || (as it removes the need for brackets around the assignment).

Alternate solution, 45 bytes, using recursion and regex:

f=s->s!=(s=replace(s,r"(.).*\K\1",""))?f(s):s

Julia, 17 bytes

(Alternate version)

s->join(union(s))

This uses union as basically a substitute for unique - I don't consider this the "real" answer, as I interpret "don't use unique" to mean "don't use a single built-in function that has the effect of returning the unique elements".

Glen O

Posted 2015-10-04T14:46:30.477

Reputation: 2 548

I had a similar idea but it wasn't as concise. Nice work! – Alex A. – 2015-10-04T17:38:28.623

3

Perl, 54 27 bytes

map{$h{$_}||=print}<>=~/./g
123456789012345678901234567

Test:

$ echo Type unique chars! | perl -e 'map{$h{$_}||=print}<>=~/./g'
Type uniqchars!
$

steve

Posted 2015-10-04T14:46:30.477

Reputation: 2 276

1print exists($h{$_})?"":$_$h{$_}||print – manatwork – 2015-10-04T16:25:36.970

Has SO inserted a unicode → char in there rendering it broken? – steve – 2015-10-04T16:29:05.123

1using a statement modifier would save you some bytes, along with @manatwork's suggestion $h{$_}||=print and using <>=~/./g should help save a few more as well! – Dom Hastings – 2015-10-04T16:30:25.083

1No, I inserted it, with the meaning of “change to”. – manatwork – 2015-10-04T16:30:34.763

1Changing to map would also improve the saving: map{$h{$_}||=print}<>=~/./g – manatwork – 2015-10-04T16:32:47.633

@manatwork - many thanks, will revise. – steve – 2015-10-04T18:28:46.363

3

PHP, 72 Bytes 84 Bytes

<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a));

Uses the characters as keys for an associative array, then prints the keys. Order of array elements is always the order of insertion.

Thanks Ismael Miguel for the str_split suggestion.

Fabian Schmengler

Posted 2015-10-04T14:46:30.477

Reputation: 1 972

1<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a)); Shorter and does the same. – Ismael Miguel – 2015-10-04T20:27:49.890

Found a shorter loop: while($c=$argv[1][$i++*1]). This replaces the whole foreach. Everything else is the same – Ismael Miguel – 2015-10-04T20:43:33.583

I tried something similar first but refrained from it because it would stop on a character that coerces to "false", i.e. "0". Try "abc0def" as input. – Fabian Schmengler – 2015-10-04T20:47:20.620

You're right about it. Surelly there's a workaround for it that doesn't cost more than 2 bytes. – Ismael Miguel – 2015-10-04T20:48:48.930

3

Pyth, 7 bytes

soxzN{z

Pseudocode:

z = input

sum of order-by index in z of N over set of z.

isaacg

Posted 2015-10-04T14:46:30.477

Reputation: 39 268

3

Java, 78 bytes

String f(char[]s){String t="";for(char c:s)t+=t.contains(c+"")?"":c;return t;}

A simple loop while checking the output for characters already present. Accepts input as a char[].

Geobits

Posted 2015-10-04T14:46:30.477

Reputation: 19 061

3

C - 58

Thanks to @hvd and @AShelly for saving a bunch of characters. There were multiple ways suggested of making it much shorter than the original:

// @hvd     - always copy to q but only increment q if not found
g(char*s,char*r){char*q=r;for(;*q=*s;q+=q==strchr(r,*s++));}

// @AShelly - keep a histogram of the usage of each character
h(char*s){int a[128]={0};for(;*s;s++)a[*s]++||putchar(*s);}

// @hvd     - modify in place
i(char*s){char*q=s,*p=s;for(;*q=*p;q+=q==strchr(s,*p++));}

// original version - requires -std=c99
void f(char*s,char*r){for(char*q=r;*s;s++)if(!strchr(r,*s))*q++=*s;}

As you can see modifying in place seems to be the shortest (so far!) The test program compiles without warnings using gcc test.c

#include <stdlib.h> // calloc
#include <string.h> // strchr
#include <stdio.h>  // puts, putchar

// 000000111111111122222222223333333333444444444455555555556666666666
// 456789012345678901234567890123456789012345678901234567890123456789

// @hvd     - always copy to q but only increment q if not found
g(char*s,char*r){char*q=r;for(;*q=*s;q+=q==strchr(r,*s++));}

// @AShelly - keep a histogram of the usage of each character
h(char*s){int a[128]={0};for(;*s;s++)a[*s]++||putchar(*s);}

// @hvd     - modify in place
i(char*s){char*q=s,*p=s;for(;*q=*p;q+=q==strchr(s,*p++));}

/* original version - commented out because it requires -std=c99
void f(char*s,char*r){for(char*q=r;*s;s++)if(!strchr(r,*s))*q++=*s;}
*/

// The test program:
int main(int argc,char*argv[]){
  char *r=calloc(strlen(argv[1]),1); // make a variable to store the result
  g(argv[1],r);                      // call the function
  puts(r);                           // print the result

  h(argv[1]);                        // call the function which prints result
  puts("");                          // print a newline

  i(argv[1]);                        // call the function (modifies in place)
  puts(argv[1]);                     // print the result
}

Thanks for all the help. I appreciate all the advice given to shorten so much!

Jerry Jeremiah

Posted 2015-10-04T14:46:30.477

Reputation: 1 217

Well, since your code already isn't valid C, just accepted by lenient C compilers: you can declare r as int (and omit the int) to save some bytes: f(s,r)char*s;{...}. But it limits your code to platforms where char* is the same size as int, and of course where compilers are as lenient as yours and mine. – hvd – 2015-10-06T09:00:18.680

@hvd That's evil! I was willing to default the return value because I don't use it. But that's a bit more dodgy than I would like to be. I think I would prefer making it compliant rather than going that far! Thanks for bringing back to the light side. – Jerry Jeremiah – 2015-10-06T09:07:37.697

You can save one char by replacing if(x)y with x?y:0 – ugoren – 2015-10-06T12:17:10.123

Here's a 60 char function that writes to stdout instead of an array parameter: f(char*s){int a[128]={0};for(;*s;s++)a[*s]++?0:putchar(*s);} – AShelly – 2015-10-06T17:29:47.893

You can unconditionally copy into *q, and only increment q if the character appeared earlier, allowing stuffing a bit more together: void f(char*s,char*r){for(char*q=r;*q=*s;strchr(r,*s++)<q||q++);} (Note that strchr(r,*s++)<q is always well-defined, there's no UB there, because strchr cannot return NULL in this version.) Except for the return type, it's even shorter than @AShelly's version. – hvd – 2015-10-06T17:30:11.787

@AShelly a[*s]++||putchar(*s) makes it a tie. – hvd – 2015-10-06T17:34:54.983

And q+=q==strchr(r,*s++) is saving one more byte over strchr(r,*s++)<q||q++. – hvd – 2015-10-06T17:46:01.330

You guys are amazing. I am so impressed. I obviously have lots to learn! – Jerry Jeremiah – 2015-10-06T20:57:22.397

Oh wait -- AShelly's version is valid C90 so can leave the return type out. My version like yours needs C99 for the declaration in the for loop, which doesn't allow omitting the return type, but C99 does allow explicitly specifying the return type as int and then not returning any value. int is shorter than void, so that saves a byte. Alternatively, the declaration in the for loop can be moved out of it, making it valid C90, and then the return type can be omitted. Also, both your version and mine would work if they modify the string in place, allowing one parameter to be removed. – hvd – 2015-10-07T08:54:15.383

@hvd Thanks for the idea about modifying in place. I have added that. I comes out one character shorter - hopefully I didn't miss any golfing opportunities this time.. – Jerry Jeremiah – 2015-10-11T11:45:50.063

3

C, 96 bytes

#include<stdio.h> 
int c,a[128];main(){while((c=getchar())-'\n')if(!a[c])a[c]=1,putchar(c);}

This uses an array of integers, indexed by ASCII character number. The characters are only printed if that place in the array is set to FALSE. After each new character is found that place in the array is set to TRUE. This takes a line of text from standard input, terminated by a newline. It ignores non-ASCII characters.


Ungolfed:

#include<stdio.h>
#include<stdbool.h>

int main(void)
{
  int i, c;
  int ascii[128];
  for (i = 0; i < 128; ++i) {
    ascii[i] = false;
  }
  while ((c = getchar()) != '\n') {
    if (ascii[c] == false) {
      ascii[c] = true;
      putchar(c);
    }
  }
  puts("\n");
  return(0);
}

musarithmia

Posted 2015-10-04T14:46:30.477

Reputation: 531

2

Ruby, 19 + 1 = 20 bytes

Uses the -p flag. Uses set operations like the GolfScript answer, which is totally not a built-in like uniq. (Performing set or on a list and an empty list purges the list of duplicates, just like calling and against a copy of itself.)

$_=($_.chars|[])*""

Value Ink

Posted 2015-10-04T14:46:30.477

Reputation: 10 608

2

Matlab, 46 bytes

It uses an anonymous function, with function arguments as input and output:

@(s)eval('s(~any(triu(bsxfun(@eq,s,s''),1)))')

(I couldn't get this to work in an Octave online interpreter.)

Example use:

>> @(s)eval('s(~any(triu(bsxfun(@eq,s,s''),1)))')
ans = 
    @(s)eval('s(~any(triu(bsxfun(@eq,s,s''),1)))')

>> ans('Type unique chars!')
ans =
Type uniqchars!

Luis Mendo

Posted 2015-10-04T14:46:30.477

Reputation: 87 464

that would have been my idea as well :) - you don't need the ,1 with any, btw. – Jonas – 2015-10-04T20:57:04.990

@Jonas Thanks! Alrhough it's hard to see through that mess of parentheses, the 1 is for triu (I need to remove the diagonal), not for any – Luis Mendo – 2015-10-04T22:36:04.830

2

Ruby, 30 24 characters

(23 characters code + 1 character command line option.)

gsub(/./){$`[$&]?"":$&}

Sample run:

bash-4.3$ ruby -pe 'gsub(/./){$`[$&]?"":$&}' <<< 'hello world'
helo wrd

manatwork

Posted 2015-10-04T14:46:30.477

Reputation: 17 865

2

CJam, 9

Lq{1$-+}/

This doesn't convert a string to a set, but it performs a kind of set difference to determine whether a character is found in a string. Try it online

Explanation:

L       push an empty array/string
q       read the input
{…}/    for each character in the input
  1$    copy the previous string
  -     subtract from the character (set difference),
         resulting in the character or empty string
  +     append the result to the string

Another version, 13 bytes:

Lq{_2$#)!*+}/

This doesn't do anything related to sets. Try it online

Explanation:

L       push an empty array/string
q       read the input
{…}/    for each character in the input
  _     duplicate the character
  2$    copy the previous string
  #)    find the index of the character in the string and increment it
  !     negate, resulting in 0 if the character was in the string and 1 if not
  *     repeat the character that many times
  +     append the result to the string

aditsu quit because SE is EVIL

Posted 2015-10-04T14:46:30.477

Reputation: 22 326

2

TI-BASIC, 49 bytes

Input Str1
"sub(Str1,X,1→Y₁
Y₁(1
For(X,2,length(Str1
If not(inString(Ans,Y₁
Ans+Y₁
End
Ans

The equation variables are rarely useful since they take 5 bytes to store to, but Y₁ comes in handy here as the Xth character of the string, saving 3 bytes. Since we can't add to empty strings in TI-BASIC, we start the string off with the first character of Str1, then loop through the rest of the string, adding all characters not already encountered.

prgmQ
?Why no empty st
rings? Because T
I...
Why noemptysrig?Bcau.

lirtosiast

Posted 2015-10-04T14:46:30.477

Reputation: 20 331

2

Befunge-93, 124 bytes

v
<v1p02-1
0_v#`g00: <0_@#+1::~p
 1>:1+10p2+0g-!#v_v
g `#v_10g0^       >:10g00
 ^0g 00$        <
 ^  >:,00g1+:00p1+:1+01-\0p

Test it in this online interpreter.


This was more difficult than I expected. I'll post a fuller explanation tomorrow if anyone wants me to, but here's an overview of what my code does.

  • Unique characters seen so far are stored on the first row, starting from 2,0 and extending to the right. This is checked against to see if the current character is a duplicate.
  • The number of unique characters seen so far is stored in 0,0 and the check-for-duplicate loop counter is stored in 1,0.
  • When a unique character is seen, it is stored on the first row, printed out, and the counter in 0,0 is incremented.
  • To avoid problems with reading in the spaces present (ASCII 32), I put the character corresponding to -1 (really, 65536) in the next slot for the next unique character.

El'endia Starman

Posted 2015-10-04T14:46:30.477

Reputation: 14 504

2

PHP, 56 54

// 56 bytes
<?=join('',array_flip(array_flip(str_split($argv[1]))));

// 54 bytes
<?=join(!$a='array_flip',$a($a(str_split($argv[1]))));

Edging out @fschmengler's answer using array_flip twice - second version uses variable method and relies on casting the string to true, negating it to false, then casting it back to the empty string in the first argument to save a couple of bytes in the second. Cheap!

Niet the Dark Absol

Posted 2015-10-04T14:46:30.477

Reputation: 647

2

Haskell, 29 bytes

Nestable, no-variable-name one-liner:

foldr(\x->(x:).filter(x/=))[]

Same count, saved into a function named f as a top-level declaration:

f(x:t)=x:f[y|y<-t,x/=y];f_=[]

Note that there is a slightly-cheating optimization which I haven't made in the spirit of niceness: it is technically still allowed by the rules of this challenge to use a different input and output encoding for a string. By representing any string by its partially-applied Church encoding \f -> foldr f [] string :: (a -> [b] -> [b]) -> [b] (with the other side of the bijection provided by the function ($ (:))) this gets golfed down to ($ \x->(x:).filter(x/=)), only 24 characters.

I avoided posting the 24-character response as my official one because the above solution could be tried on the above interpreter as foldr(\x->(x:).filter(x/=))[]"Type unique chars!"whereas the golfed solution would be written instead:

($ \x->(x:).filter(x/=))$ foldr (\x fn f->f x (fn f)) (const []) "Type unique chars!"

as a shorthand for the literal declaration which would be the more-insane:

($ \x->(x:).filter(x/=))$ \f->f 'T'.($f)$ \f->f 'y'.($f)$ \f->f 'p'.($f)$ \f->f 'e'.($f)$ \f->f ' '.($f)$ \f->f 'u'.($f)$ \f->f 'n'.($f)$ \f->f 'i'.($f)$ \f->f 'q'.($f)$ \f->f 'u'.($f)$ \f->f 'e'.($f)$ \f->f ' '.($f)$ \f->f 'c'.($f)$ \f->f 'h'.($f)$ \f->f 'a'.($f)$ \f->f 'r'.($f)$ \f->f 's'.($f)$ \f->f '!'.($f)$ const[]

But it's a perfectly valid version of the data structure represented as pure functions. (Of course, you can use \f -> foldr f [] "Type unique chars!" too, but that is presumably illegitimate since it uses lists to actually store the data, so its foldr part should then presumably be composed into the "answer" function, leading to more than 24 characters.)

CR Drost

Posted 2015-10-04T14:46:30.477

Reputation: 949

2

C, 47 bytes

a[];main(c){for(;read(0,&c,1);write(!a[c]++));} 

xsot

Posted 2015-10-04T14:46:30.477

Reputation: 5 069

2

Simplex v.0.7, 22 10 bytes

s^oR^l^Ryg
s          ~~ string input
 ^o        ~~ convert to tuple
   R       ~~ go right
    ^l     ~~ unicode tuple
      ^R   ~~ take intersection
        yg ~~ convert to string and output

sigh Minkolang is kicking Simplex's butt.

s^[oZ%_Q]n?[^_s^~M^=]]
s                      ~~ string input
 ^[     ]              ~~ postfixes each of the inner with a ^
   o                   ~~ convert to tuple
    Z                ] ~~ fold
     %                 ~~ tuple w/out current character + increment
      _                ~~ current character
       Q               ~~ membership
         n?[        ]  ~~ if current character not in tuple
            ^_s^~M^=   ~~ print that character 

Conor O'Brien

Posted 2015-10-04T14:46:30.477

Reputation: 36 228

2What a coup for Simplex! – El'endia Starman – 2015-10-28T02:51:40.847

2

Octave, 25 bytes

@(s)s(sum(triu(s'==s))<2)

alephalpha

Posted 2015-10-04T14:46:30.477

Reputation: 23 988

2

Javascript (ES6), 47 bytes

a=>[...a].filter((b,c)=>a.indexOf(b)==c).join``

Test it here

Some code is added to have a better input and to write to the console the result.

d=document,g=d.getElementById.bind(d);g("s").onclick=e=>console.log((a=>[...a].filter((b,c)=>a.indexOf(b)==c).join``)(g("t").value))
<input id="t"><button id="s">Convert</button>

user54187

Posted 2015-10-04T14:46:30.477

Reputation:

2

Vim, 23 keystrokes

qq:s/\v(.).*\zs\1<cr>@qq@q

Explanation:

qq                           " Start recording into register 'q'
  :s/                        " Search and replace:
      \v                     " Enable 'magic', which just makes regexes a littl shorter
        (.)                  " Any symbol, captured in group one
           .*                " Anything
             \zs\1           " Start selection, group one
                             " Replace with nothing
                  <cr>       " Globally
                      @q     " Call macro q. Since we are still recording, this will not do anything the first time, and create a loop the next time
                        q    " Stop recording. 
                         @q  " Start the loop. This will run until there is no match.

Since V is backwards compatible, you can Try it online!

James

Posted 2015-10-04T14:46:30.477

Reputation: 54 537

1

REXX, 79 bytes

a=arg(1)
o=
do while a>''
  parse var a b+1 a
  if pos(b,o)=0 then o=o||b
  end
say o

idrougge

Posted 2015-10-04T14:46:30.477

Reputation: 641

1

Python, 61 59 bytes

lambda s:''.join(i for c,i in enumerate(s)if s.index(i)==c)

str.index always returns the first occurrence, so only output the character if the current occurrence is the first occurrence.

Edit: The square brackets were unnecessary.

HyperNeutrino

Posted 2015-10-04T14:46:30.477

Reputation: 26 575

1

PHP, 47 Bytes

for(;a&$c=$argn[$i++];)$r[$c]=$c;echo join($r);

Try it online!

Jörg Hülsermann

Posted 2015-10-04T14:46:30.477

Reputation: 13 026

1

AutoIt, 107

Func _($0)
$1=''
For $2 In StringSplit($0,'',3)
$1&=StringInStr($1,$2,1)?'':$2
Next
Return $1
EndFunc

Call it like any function:

ConsoleWrite(_("Type unique chars!"))

mınxomaτ

Posted 2015-10-04T14:46:30.477

Reputation: 7 398

1

Haskell, 50

f=concat.(tail>>=zipWith(\x y->[last x]\\y)).inits

proud haskeller

Posted 2015-10-04T14:46:30.477

Reputation: 5 866

3inits is in Data.List, so you need an import, which is usually added to the byte count. – nimi – 2015-10-04T20:46:25.107

1

Java, 79 bytes

It's java, and it may be a little bit shorter than some of the more wordy esoteric languages.

But still, java.

s->{String r="";for(char c:s.toCharArray())r+=(r.indexOf(c)>-1)?"":c;return r;}

Explanation:

s->{ //Lambda expression opening, note that java can infer the type of s

    String r=""; //Initializes String r

    for(char c:s.toCharArray()) //Iterates through the string

        r+=(r.indexOf(c)>-1)?"":c; //indexOf(c) returns -1 if there are no occurrences

    return r;

}

Daniel M.

Posted 2015-10-04T14:46:30.477

Reputation: 3 737

I know it's been about 2.5 years, but you can golf it to s->{String r="";for(String c:s.split(""))r+=r.indexOf(c)<0?c:"";return r;}, or even six bytes shorter when using Java 10 instead of 8, so both String can be var. And I'm not 100% sure it's allowed, but I think you can just input it as a String-array instead so .split("") can be removed. In total: s->{var r="";for(var c:s)r+=r.indexOf(c)<0?c:"";return r;} Try it online 58 bytes. (Or alternatively: s->{var r="";for(var c:s)r=r.indexOf(c)<0?r+c:r;return r;} Also 58 bytes.)

– Kevin Cruijssen – 2018-04-06T14:52:34.087

1

Python 3, 132 109 105 bytes

u=[]
def t(l):
 if l in u:return''
 else:
  u.append(l);return l
print(''.join([t(l)for l in input()]))

Ungolfed:

used_chars = []
def test(letter):
    if letter in used_chars:
        return '' # skip
    else:
        used_chars.append(letter)
        return letter
print(''.join([test(letter) for letter in input()]))

J F

Posted 2015-10-04T14:46:30.477

Reputation: 281

Shouldn't the r(l) in the last line be t(l)? – None – 2015-10-05T09:16:48.770

Also, you can use print if you end the line with a comma: print ('%s') % (''.join([r(l)for l in i])), then import sys won't be necessary. – None – 2015-10-05T09:19:23.907

Following Thomas Kwa's suggestion, one trailing \n is acceptable in stdout (in fact it's implicit in many functions used for displaying into stdout). I've made this explicit in the challenge rules. You may perhaps use that to reduce your code length – Luis Mendo – 2015-10-05T09:54:53.580

1

Delphi, 111 bytes

procedure u(var s:string);var i:word;begin for i:=length(s) downto 1 do if pos(s[i],s)<i then delete(s,i,1)end;

Using the procedure to alter the passed in string - saves a few bytes in comparison to declaring the function. Moving backwards through the string, delete the current character if it is not the first location of that character

James

Posted 2015-10-04T14:46:30.477

Reputation: 31

1

JavaScript (ES6) 46

f=s=>[...s].map(c=>s[c]?'':s[c]=c,s=[]).join``

Unexpectedly, this time the flag array is one byte shorter than the indexOf approach.

edc65

Posted 2015-10-04T14:46:30.477

Reputation: 31 086

1

SED, 61 bytes

s/^/\a/
:
s/\a\(\(.\).*\)\2/\a\1/
t
s/\a\(.\)/\1\a/
t
s/\a//

Hasturkun

Posted 2015-10-04T14:46:30.477

Reputation: 1 206

12 characters shorter: s/\a\(.\)\(.*\)\1/\a\1\2/s/\a\(\(.\).*\)\2/\a\1/. If you have GNU sed you can remove the parenthesis escaping at the price of +1 for the -r switch. – manatwork – 2015-10-06T13:43:12.250

@manatwork: Nice, changed. (I could also shrink all \a sequences into a single unprintable BEL character, though I'm not sure it's really worth it) – Hasturkun – 2015-10-06T14:08:07.377

1

Perl 5.10+, 21 bytes

perl -pe '1while s/(.).*\K\1//'

20 bytes + 1 byte for -p. Note that Perl 5.10 or above is required for \K.

Takes input from stdin:

$ echo 'Type unique chars!' | perl -pe '1while s/(.).*\K\1//'
Type uniqchars!

$ echo \"I think it\'s dark and it looks like rain\", you said | perl -pe '1while s/(.).*\K\1//'
"I think'sdarloe,yu

$ echo 3.1415926535897932384626433832795 | perl -pe '1while s/(.).*\K\1//'
3.14592687

Online demo


Inspired by NinjaBearMonkey's Retina answer. Perl may not have a compact way to re-run a substitution until nothing changes, but it does have \K, which causes the regex engine to "keep" everything to its left. This allows you to drop a set of parentheses on the LHS and a capture variable on the RHS:

s/(.).*\K\1//   # 13 bytes

vs.

s/((.).*)\2/$1/ # 15 bytes

ThisSuitIsBlackNot

Posted 2015-10-04T14:46:30.477

Reputation: 1 050

1Save 1 byte using s/(.).*\K\1//&&redo – Ton Hospel – 2016-09-28T11:50:42.530

1

Perl 6, 32 bytes

The way you would normally write this would be:

$*IN.comb.unique.print # it would have been 22

Which would have had the benefit of being obviously correct.


Instead I have to write something like the following

print $*IN.comb.grep:{!.{$^a}++} # 32

Brad Gilbert b2gills

Posted 2015-10-04T14:46:30.477

Reputation: 12 713

1

Minkolang 0.10, 13 bytes

This language was made after this challenge but not for this challenge.

Much thanks to Sp3000 for pointing me the way to this much shorter solution.

od?.dd0q?Od0p

Try it here.

Explanation

od               Read character from input and duplicate it (for the conditional)
  ?.             Stop if 0 (i.e., input is empty)
    dd           Duplicate twice (for q and for possible output)
      0q         Gets value stored in (character,0) in the codebox (0 if empty)
        ?O       Outputs character if it's unique (i.e. the previous value was 0)
          d0p    Puts the value of the character at (value,0) in the codebox

El'endia Starman

Posted 2015-10-04T14:46:30.477

Reputation: 14 504

1

AppleScript, 143 142 Bytes

set x to(display dialog""default answer"")'s text returned's characters
set o to""
repeat with i in x
if not i is in o then set o to o&i
end
o

Not a language for golfing, but it's very readable.

Addison Crump

Posted 2015-10-04T14:46:30.477

Reputation: 10 763

1

R, 52 bytes

cat(union(a<-strsplit(readline(),"")[[1]],a),sep="")

Test examples:

Type uniqchars!
"I think'sdarloe,yu
3.14592687

Andreï Kostyrka

Posted 2015-10-04T14:46:30.477

Reputation: 1 389

1

RProgN, 85 Bytes, Non Competing

S i 'a' = s 'n' = a L while a pop 'b' = n b hasvalue ! if n b push end a L end n i ++

Explanation

S i                     # Take the implicit string input, convert it to a stack such that the first letter is at the bottom, invert the stack such that the first letter is at the top.
'a' =                   # Associate it with 'a'
s 'n' =                 # Create a new stack, associate it with 'n'
a L                     # Push the size of a
while                   # While the top of the stack contains a truthy value
    a pop 'b' =         # Pop the top of a, associate it with 'b'
    n b hasvalue !      # Push if the stack 'n' does not contain b
    if                  # If the top of the stack is truthy
        n b push        # Push b to the stack n
    end                 #
    a L                 # Push the length of a
end                     # loop
n i ++                  # Push the n, inverts it, sums it, which acts to concatenate it, implicitly print the result.

Non-Competing as the 'Not' and 'HasValue' functions were both not implemented prior to this challenge.

ATaco

Posted 2015-10-04T14:46:30.477

Reputation: 7 898

0

Python 2, 79

def S(s):
 s=s[::-1]
 for c in s:s=s.replace(c,'',s.count(c)-1)
 return s[::-1]

It reverses the input string, cycles through it, replaces any extra characters with null ones and returns the reverse of that. The reverse is so the last characters are removed, not the first.

>>> S('''"I think it's dark and it looks like rain", you said''')
'"I think\'sdarloe,yu'
>>> S("3.1415926535897932384626433832795")
'3.14592687'
>>> S("Type unique chars!")
'Type uniqchars!'

Status

Posted 2015-10-04T14:46:30.477

Reputation: 995

0

Haskell, 33 bytes

foldl(\r c->r++[c|notElem c r])[]

Uses foldl to iterate through the string appending characters that are not in the current result, starting with the empty string (list).

xnor

Posted 2015-10-04T14:46:30.477

Reputation: 115 687

0

Scala, 118 bytes

def f(a:String):String={a=>a.zipWithIndex.groupBy(_._1.toLower).map(_._2.head).toList.sortBy(_._2).map(_._1).mkString}

Leonardo

Posted 2015-10-04T14:46:30.477

Reputation: 11

0

MUMPS, 54 bytes

f(s) f i=1:1:$L(s) s c=$E(s,i) s:t'[c o=o_c,t=t_c
    q o

Not terribly exciting - it just keeps a running list of already-viewed characters and only appends to the output string if the current character isn't in that list.

senshin

Posted 2015-10-04T14:46:30.477

Reputation: 641

0

Powershell, 30

$args-replace'(.)(?<=\1.+)',''

I feel there's likely to be a better regex than this, and I can't work out what it is

tomkandy

Posted 2015-10-04T14:46:30.477

Reputation: 167

0

Ceylon, 98 bytes (stdio) / 69 bytes (function)

This version is using stdio and a HashSet, 98 bytes:

import ceylon.collection{H=HashSet}shared void u(){print(String(H{*(process.readLine()else"")}));}

This is just a function String → String (also using a HashSet), 69 bytes:

import ceylon.collection{H=HashSet}String n(String i)=>String(H{*i});

Ungolfed version:

import ceylon.collection {
    HashSet
}
void uniq() {
    value input = process.readLine() else "";
    value set = HashSet { elements = input; };
    print(String(set));
}

A Ceylon HashSet by default is linked (i.e. conserves the insertion order as iteration order). We use here the named-argument syntax to pass the elements argument to the HashSet constructor.

A string is also an iterable of characters, and as such can be passed to the elements parameter. A string can also be constructed from such a sequence, which is what we do in the last command.

The golfed version again: import ceylon.collection{H=HashSet}shared void u(){print(String(H{*(process.readLine()else"")}));}

Some used tricks:

  • Variable inlining
  • If we have to import HashSet anyways, give it a shorter name.
  • The named-argument syntax accepts also a "normal" argument list. Any arguments in that list will be, if they don't fit the other arguments, be wrapped in an Iterable and passed to an Iterable argument (if there is one). To spread our existing iterable (the input string) into such an argument list, we use the "spread operator *".

If we don't have to handle standard-input and output and just need a function, this is shorter:

import ceylon.collection{HashSet}
String n(String i) => String(HashSet{*i});

The explanations from above are still valid.

Paŭlo Ebermann

Posted 2015-10-04T14:46:30.477

Reputation: 1 010

0

Ceylon, 98 bytes (stdio) / 68 bytes (function)

Here is a version without using Set or similar stuff, as a function (68 bytes):

String i(String s)=>String{for(x->c in s.indexed)if(!c in s[0:x])c};

The same with stdio (reading just one line) (98 bytes):

void q(){value s=process.readLine()else"";print(String{for(x->c in s.indexed)if(!c in s[0:x])c});}

The first one ungolfed (117 bytes):

String i(String s) => String{
        for (x->c in s.indexed)
            if (!c in s[0:x])
                c
    };

This uses the feature to build a string from an iterable of characters, but this time the iterable is build from a comprehension, which is passed to the string-constructor using the named-argument-list syntax. (This could also have been written as String({...});, using a positional argument list and an iterable-constructor, but that would have been two bytes more).

The comprehension consists of a for-clause (which iterates over an indexed version of the input string, i.e. x is the index corresponding to the character c) and an if-clause (which filters the character by checking if it appears in the substring up to the index).

We see here two different uses of the keyword in – once as part of the syntax of the for clause of comprehensions, and once as the in operator, which maps to s[0:x].contains(c).

The "thin arrow" in x->c is the syntax for an Entry made of x and c (as key and value). As an expression one can build an entry this way from its constituents, but here it is a part of the comprehension syntax (and also the syntax of the for-loop), and deconstructs the entry which is returned by the iterator of the iterable s.indexed.

The "fat arrow" => is a shorthand for defining a function whose body consists of just one expression (which is evaluated and returned) – that saves us the return and a pair of braces.

The variant which uses stdio:

void q() {
    value s = process.readLine() else "";
    print(String { for (x->c in s.indexed)
                if (!c in s[0:x])
                    c });
}

Unfortunately we need a variable here to store the string, because we need to access it twice (in the loop and in the filter).


Instead of using an Iterable comprehension, we can also use the stream-manipulating method filter together with the spread attribute operator *. and a lambda expression (e)=>!e.item in s[0:e.key] inbetween:

String j(String s)=>String(s.indexed.filter((e)=>!e.item in s[0:e.key])*.item);

This is even longer with 79 bytes.

Paŭlo Ebermann

Posted 2015-10-04T14:46:30.477

Reputation: 1 010

0

Rust, 318 Bytes

not really a competitor, but rust needs a bit more love. As always, comments and advice welcome.

use std::io;fn main(){let mut s=io::stdin();let mut b=String::new();s.read_line(&mut b).unwrap();let mut n: Vec<char>=b.chars().collect();for i in 0..n.len()-2{let mut j=i+1;let mut p = true;while j<n.len(){if j<n.len(){if n[i]==n[j]{n.remove(j);p=false;}}if p{j+=1;}p=true;}}for i in 0..n.len()-2{print!("{}",n[i]);}}

Try it online here (first compile, then execute, then click into the proper area to enter user input)

ungolfed:

use std::io;
fn main() {
let mut s = io::stdin();
let mut b=String::new();
s.read_line(&mut b).unwrap();
let mut chars: Vec<char> = b.chars().collect();
for i in 0..chars.len()-2 {
    let mut j=i+1;
    let mut inc = true;
    while j<chars.len() {
        if j<chars.len() 
        {
            if chars[i]==chars[j] {
                chars.remove(j);
                inc = false;
            }
        }
        if inc {
            j+=1;
        }
        inc = true;
    }
}
for i in 0..chars.len()-2 {
    print!("{}",chars[i]);
}
}

Liam

Posted 2015-10-04T14:46:30.477

Reputation: 3 035

0

Python 2, 62 bytes

s=set();print filter(lambda i:not(i in s or s.add(i)),input())

Zach Gates

Posted 2015-10-04T14:46:30.477

Reputation: 6 152

0

Python, 62 bytes

lambda s:''.join([c for i,c in enumerate(s)if c not in s[:i]])

tobilocker

Posted 2015-10-04T14:46:30.477

Reputation: 101

It's scored by size in bytes, I'll just edit it so its right... Also, you can move the space between the : ''.join so it's like :''.join – Blue – 2015-10-06T16:27:30.373

I don't think you need the outer square brackets. – HyperNeutrino – 2017-03-23T12:58:22.733

0

Scala, 79, 66 bytes

Inspired by the Haskell version using foldLeft

def f(s:String)=s.foldLeft("")((a,c)=>if(a.contains(c))a else a+c)

Previous version using zipWithIndex and collect

def f(s:String)=s.zipWithIndex.collect{case(c,i)if s.indexOf(c)==i=>c}.mkString

JoseM

Posted 2015-10-04T14:46:30.477

Reputation: 101

0

Gema, 18 characters

?=${?;$0}@set{$0;}

Sample run:

bash-4.3$ gema '?=${?;$0}@set{$0;}' <<< 'hello world'
helo wrd

manatwork

Posted 2015-10-04T14:46:30.477

Reputation: 17 865