| Bytes | Lang | Time | Link |
|---|---|---|---|
| 056 | C | 151005T212126Z | Jerry Je |
| 066 | Bash | 241112T130458Z | Themooni |
| 042 | Zsh | 241113T061455Z | roblogic |
| 007 | Uiua | 241113T022526Z | nyxbird |
| 005 | Japt f | 241112T115021Z | Shaggy |
| 058 | brainfuck | 241112T061933Z | l4m2 |
| 020 | x86 opcode | 241112T064932Z | l4m2 |
| nan | 241112T045323Z | gurditsb | |
| 126 | Rockstar | 230608T202524Z | Shaggy |
| 001 | Thunno 2 J | 230608T190222Z | The Thon |
| 013 | Z80Golf | 221107T113320Z | EasyasPi |
| 034 | nanoMIPS machine code | 221107T065049Z | EasyasPi |
| 085 | RProgN | 160928T013801Z | ATaco |
| 088 | C 88 Bytes | 220328T013252Z | user1117 |
| 002 | Vyxal | 220325T080825Z | emanresu |
| 030 | Lexurgy | 220324T155925Z | bigyihsu |
| 070 | Lua | 220323T231213Z | twentysi |
| 002 | ngn/k | 220324T001216Z | ulucs |
| 034 | GNU AWK | 210116T055008Z | Pedro Ma |
| 021 | i386 machine code | 210117T231737Z | EasyasPi |
| 008 | Pyth | 210118T031342Z | Scott |
| 023 | Red | 210115T114037Z | Galen Iv |
| 005 | Stax | 210115T104347Z | Razetime |
| 019 | Perl 5 + p | 151004T163242Z | Dom Hast |
| 014 | K ngn/k | 210114T191249Z | coltim |
| 003 | Jelly | 210114T181425Z | caird co |
| 114 | Scala | 151005T101739Z | Leonardo |
| 021 | sed E | 200611T161543Z | Mitchell |
| 004 | 05AB1E | 200611T133211Z | Kevin Cr |
| 9868 | Ceylon | 151005T204531Z | Paŭlo Eb |
| 9869 | Ceylon | 151005T194821Z | Paŭlo Eb |
| 026 | Python 3 | 200609T190733Z | xnor |
| 047 | PHP | 170517T154447Z | Jör |
| 059 | Python | 170323T125359Z | hyperneu |
| 062 | Python | 151006T155857Z | tobilock |
| 018 | Beam | 151004T193749Z | MickyT |
| nan | Ruby | 170322T202018Z | Value In |
| 079 | REXX | 170322T103355Z | idrougge |
| 052 | R | 160928T012955Z | Andre |
| 023 | Vim | 160927T230857Z | DJMcMayh |
| 047 | Javascript ES6 | 160628T155811Z | user5418 |
| 003 | APL | 151006T143820Z | Moris Zu |
| 025 | Octave | 151029T154229Z | alephalp |
| 142 | AppleScript | 151029T152756Z | Addison |
| 018 | Gema | 151029T143650Z | manatwor |
| 010 | Simplex v.0.7 | 151028T022146Z | Conor O& |
| 013 | Minkolang 0.10 | 151028T022814Z | El'e |
| 047 | C | 151028T013844Z | xsot |
| 032 | Perl 6 | 151027T234052Z | Brad Gil |
| nan | 151005T143542Z | hvd | |
| 066 | Scala | 151007T170222Z | JoseM |
| 029 | Haskell | 151007T002144Z | CR Drost |
| 105 | Python 3 | 151005T013602Z | J F |
| 021 | Perl 5.10+ | 151006T204317Z | ThisSuit |
| 062 | Python 2 | 151006T141541Z | Zach Gat |
| 061 | SED | 151006T132957Z | Hasturku |
| 318 | Rust | 151006T095218Z | Liam |
| 5654 | PHP | 151006T081326Z | Niet the |
| 025 | JavaScript ES7 | 151005T103138Z | azz |
| 096 | C | 151005T214416Z | musarith |
| 030 | Powershell | 151005T175110Z | tomkandy |
| 054 | MUMPS | 151005T174948Z | senshin |
| 042 | Python 2 | 151005T154514Z | mbomb007 |
| 002 | GolfScript | 151005T152403Z | Ilmari K |
| 078 | Java | 151005T133641Z | Geobits |
| 033 | Haskell | 151005T082306Z | xnor |
| 044 | Python 3 | 151005T080035Z | xnor |
| 046 | JavaScript ES6 | 151005T074201Z | edc65 |
| 124 | Befunge93 | 151005T060633Z | El'e |
| 042 | Julia | 151004T151437Z | Glen O |
| 079 | Python 2 | 151005T042949Z | Status |
| 018 | Element | 151004T145718Z | PhiNotPi |
| 016 | ><> | 151005T011815Z | Sp3000 |
| 111 | Delphi | 151005T021429Z | James |
| 079 | Java | 151005T012435Z | Daniel M |
| 007 | Pyth | 151004T233307Z | isaacg |
| 046 | Matlab | 151004T150102Z | Luis Men |
| 7284 | PHP | 151004T181705Z | Fabian S |
| 027 | Perl | 151004T162140Z | steve |
| 049 | TIBASIC | 151004T183114Z | lirtosia |
| 050 | Haskell | 151004T182036Z | proud ha |
| 014 | Retina | 151004T171133Z | NinjaBea |
| 023 | MATLAB | 151004T152812Z | Tom Carp |
| 009 | CJam | 151004T154228Z | aditsu q |
| 024 | Ruby | 151004T152507Z | manatwor |
| 047 | JavaScript ES6 | 151004T150701Z | NinjaBea |
| 233 | Macaroni 0.0.2 | 151004T152903Z | Doorknob |
| nan | 151004T150952Z | ProgramF | |
| 107 | AutoIt | 151004T150817Z | user4264 |
| 003 | CJam | 151004T145742Z | Sp3000 |
C - 56
Thanks to @ceilingcat, @hvd and @AShelly for saving a bunch of characters. There were multiple ways suggested of making it much shorter than the original:
// @ceilingcat - put vars in for loop
j(char*s){for(char*q=s,*p=s;*q=*p;q+=q==index(s,*p++));}
// @ceilingcat - use index() instead of strchr()
j(char*s){char*q=s,*p=s;for(;*q=*p;q+=q==index(s,*p++));}
// @hvd - modify in place
i(char*s){char*q=s,*p=s;for(;*q=*p;q+=q==strchr(s,*p++));}
// @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 - 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++));}
// 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!
Bash, 66 bytes
-9 bytes by roblogic
fold -1|cat -n|sort -k2 -k1n|uniq -f1|sort -nk1,1|cut -f2-|rs -eg0
Explanation:
fold -1|cat -n|sort -k2 -k1n|uniq -f1|sort -nk1,1|cut -f2-|rs -eg0
fold -1 # split string on the empty string
cat -n # add line numbers to the beggining of each line (each char)
sort -k2 -k1n # sort by the second field (the char)
uniq -f1 # keep only 1 copy of consecutive identitcal lines, ignoring line numbers in the first field
sort -nk1,1 # sort by line numbers to get back the original order
cut -f2- # keep only chars, removing the line numbers
rs -eg0 # remove trailing newlines of each line, joining each char on the empty string
💎
Created with the help of Luminespire.
Zsh, 42 bytes
for i (${(s::)1})printf "${i:|P}"&&P+=($i)
For each character i in the string $1, if it's not in array P, print it then add it to the array.
A much shorter solution, that breaks the builtin rule, is only 21 bytes: Try it online!
<<<${(j::)${(us::)1}}
Uiua, 7 bytes
⍜⊛⍜°⊚≡±
⍜ under ⊛ classifying each character, and ⍜ under °⊚ counting each number, get the ± sign of each count (counts ≥1 become 1).
(The builtin for this is ◴ deduplicate.)
x86 opcode, 20 bytes
.intel_syntax noprefix
.globl .type_uniqchars
// src: ESI: input string
// dst: EDI: output buffer (must be big enough)
// len: ECX: length of string
.type_uniqchars:
xor eax, eax
push eax
push eax
push eax
.Lloop: lodsb
bts [esp-4], eax
jc .Lloop.duplicate
.Lloop.unique:
stosb byte ptr [edi], al
.Lloop.duplicate:
loop .Lloop
.Lloop.end:
add esp, 12
ret
Save 3 bytes than EasyasPi by reducing and expanding initialization with 2 byte extra cost checking.
Notice that [esp-4] isn't used as input is ASCII and 32≤eax<127
?
- The
distinct?verb remove duplicates and preserves order ngn/k
Rockstar, 126 bytes
Listen to I
Cut I
O's ""
While I
Roll I in C
X's 0
P's 1
While O at X
If C's O at X
P's 0
Build X up
If P
Let O be+C
Say O
Try it (Code will need to be pasted in)
Or, if we can output each character individually, on a separate line ...
124 bytes
Listen to I
Cut I
O's ""
While I
Roll I in C
X's 0
P's 1
While O at X
If C's O at X
P's 0
Build X up
If P
Let O be+C
Say C
Thunno 2 J, 1 byte
ċ
Takes the set union with itself (set operations were allowed by OP).
Thunno 2 J, 11 bytes
{DȤsƇ¬?ȥ;}Ȥ
A different answer that doesn't use sets.
Explanation
{DȤsƇ¬?ȥ;}Ȥ # Implicit input
{ } # For each character in the input:
D # Duplicate it
Ȥs # Push the global array and swap
Ƈ¬? # If it's not in the global array:
ȥ; # Add it to the global array
Ȥ # After the loop, push the global array
# Implicit output, joined
Z80Golf, 13 bytes
00000000: cd 03 80 38 04 26 ff 6f cb 76 74 c5 c0 ...8.&.o.vt..
Commented assembly:
start:
.loop:
call 0x8003 ; CD 0380 Read from stdin to A, C is success
jr c, .end + 1 ; 38 04 Jump to the 76 in the middle of the bit opcode to halt
ld h, 0xFF ; 26 FF HL = 0xFFxx
ld l, a ; 6F HL = 0xFF00+A, address + offset of LUT
.end:
bit 6, (hl) ; CB 76 Test bit 6 of the table
; halt ; (76) Exit the program with halt (overlaps)
ld (hl), h ; 74 Mark the LUT to 0xFF
push bc ; C5 Push address of .loop for ret (BC is 0x0000)
ret nz ; C0 If bit 6 was set (not unique), ret to .loop
; otherwise fall through to putchar
This uses the LUT method in my other answers. However it is much easier on Z80Golf because I know the full state of the machine and can optimize for it.
Specifically, I know that the 128 bytes at 0xFF00-0xFF7F will be 0, so I can use that by setting the high byte of HL and the low byte of A.
There are some weird optimizations to make this smaller. I could get 0xFF in h in one byte by dec h, but that introduces a state I have to check. Instead, I suck up the byte for ld h, 0xFF in favor of the entire program being stateless outside of the table. Then, I can use push bc followed by ret nz to loop if nonzero or fall through the nop sled to putchar otherwise.
nanoMIPS machine code, 34 bytes
00000000: 80 1c a0 d3 fc 90 a7 23 87 04 80 bb c0 5f 89 90 .......#....._..
00000010: a7 23 07 30 00 bb a7 23 87 38 d4 5f a9 90 80 bb .#.0...#.8._....
00000020: 80 1d ..
Commented assembly:
.globl uniqchars
# Type uniqchars! for nanoMIPS, Yet Another Weird MIPS Extension
# Follows C calling convention
# void uniqchars(const char *input, char *output);
# Input:
# a0: pointer to a null terminated ASCII string
# a1: pointer to an adequately sized buffer
# Output:
# Null terminated ASCII string stored to a1
uniqchars:
# Create a 128 byte stack buffer for a lookup table
# Equivalent normieMIPS:
# addiu $sp, -128
save 128
# Clear the buffer
li $a3, 128 / 4
.Lclear:
# Decrement index
addiu $a3, -4
# Behold! MIPS finally added register-register addressing!
# And only like 31 years late!
# addiu $at, $sp, $a3
# sw $zero, ($at)
swx $zero, $a3($sp)
# Loop if not zero
bnez $a3, .Lclear
# Loop through the string
.Lloop:
# Load byte from a0
lb $a3, ($a0)
# Increment pointer
addiu $a0, 1
# Load byte from lookup table
lbx $a2, $a3($sp)
# If it is nonzero, this char is not unique. Try the next one.
bnez $a2, .Lloop
# Store the char itself to the lookup table
sbx $a3, $a3($sp)
# Store the char to the output string
sb $a3, ($a1)
addiu $a1, 1
# Loop if it was not a null terminator
bnez $a3, .Lloop
# Clean up the stack and return
# addiu $sp, 128
# jr $ra
restore.jrc 128
This uses the new nanoMIPS calling convention, and can be called from C with the following prototype:
void uniqchars(const char *input, char *output);
Yes. This is the third compressed variant of the MIPS instruction set. All three of which are incompatible.
Aside from a few "hybrid instructions" added, it is just normal MIPS in shorthand.
A GCC toolchain, QEMU port, and documentation links are in the link above. Note that for some reason the Windows port lacks qemu-nanomips and both Linux and Windows versions crash on my system unless I run it in qemu-x86_64 itself. 🤔
RProgN, 85 Bytes
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.
C - 88 Bytes
r[99];b;a;main(i){for(;read(i=0,&b,1);99-i?b=0:putchar(r[a++]=b))for(;i<99&&b-r[i++];);}
Thanks to @ceilingcat because I saved 20 bytes with his modification.
Ungolfed
r[99]; b; a;
main(i) {
for(; read(0, &b, 1); 99 - i?b = 0: putchar(r[a++] = b))
for(i = 0; i < 99 && b - r[i++]; ); }
Explanation
Characters are read from the console, which are searched for within a list containing all the repeated characters found so far, as the characters are read, the list is updated, with new characters being added at the end of the list. If a character is repeated it is not printed.
This code was tested on GCC and it generates some warnings but it compiles and works fine (although it is not the most optimized code).
Vyxal, 2 bytes
ƒ∪
Reduce by set union. Port of caird's answer.
Vyxal, 3 bytes
ÞU*
Multiply by uniquify mask.
Lexurgy, 30 bytes
Due to how Lexurgy handles whitespace, it expects whitespace to be replaced with some other character, such as _.
a propagate:
[]$1=>*/$1 []* _
Explanation
a propagate: # rule a: while the current string changed last run...
[]$1 # match anything...
=> # and replace with...
* # empty string
/ # when the input...
$1 # starts with the captured char
[]* # followed by any number of anything
_ # then a captured char
Lua, 70 bytes
l={}print(((...):gsub('.',function(c)c=l[c]or c;l[c]=''return c end)))
Attempt This Online! Stores the characters in the table after gsub walks through the whole string. Strings are truthy values in Lua so when list[character] is nil, the character is returned the first time then it is replaced with an empty string after the assignment.
ngn/k (2 bytes)
!=
= produces a dict that shows where each element is located, ! takes the keys.
GNU AWK, 35 34 bytes
BEGIN{RS=".|";ORS=e}!a[RT]++,$0=RT
This is a major edit of my first version. In fact, it changed entirely. Only works in GNU AWK, due to the RT variable.
BEGIN{RS=".|";ORS=e}
RS=".|" works like the /./ regex, so every character of the input is considered a record separator. The practical use is that RT returns each character at a time. ORS=e prevents newlines from appearing.
!a[RT]++,$0=RT
A simple AND gate. This is a range pattern. The left part: current RT element of the a array is incremented by 1, but it is evaluated by the NOT gate before the increment. Returns TRUE only the first time a character appears. The right part: assigns the current character (RT) to the input/output $0; only happens when beginning pattern is true, i.e., the first time a character appears.
AWK, 48 bytes (former answer)
split($0,a,e){for(i in a)printf a[j=a[i]]++?e:j}
{
split($0,a,e); # Splits the input into the _a_ array, one char for each element.
# _e_ variable is not assigned, and returns "".
for(i in a) # For each element _i_ of the array _a_,
printf
a[j=a[i]]++? # if the element a[i] (AKA j) is positive (i.e, true),
^--- (This also increments this element by 1 after evaluating it)
e: # prints _e_ (AKA "")
j # if it's zero (AKA not assigned, AKA false), prints a[i].
}
i386 machine code, 22 21 bytes
Machine code:
00000034 6a 20 59 6a ff e2 fc 91 ac d0 2c 04 71 01 aa e2 |j Yj......,.q...|
00000044 f7 83 ec 80 c3 |.....|
00000049
Commented assembly:
.intel_syntax noprefix
.globl .type_uniqchars
// dst: EDI: output buffer (must be big enough)
// src: ESI: input string
// len: EAX: length of string
.type_uniqchars:
// Set ECX to 32
push 32
pop ecx
// Create a 128 byte buffer on the stack of all 1 bits
// by pushing -1 32 times.
// We only need 128 bytes because we know that
// we are only dealing with ASCII.
.Lpush_loop:
push -1
loop .Lpush_loop
.Lpush_loop.end:
// ECX = len
// EAX = 0 (because of the loop)
xchg ecx, eax
.Lloop:
// AL = *src++;
lodsb al, byte ptr [esi]
// This is taking advantage of this quirk with SHR:
//
// The OF flag is affected only on 1-bit shifts [...]
// For the SHR instruction, the OF flag is set to the
// most-significant bit of the original operand.
//
// So basically, we do this:
//
// unique duplicate
// 0b11111111 0b01111111
// |\\\\\\\ |\\\\\\\
// OF:1||||||| OF:0|||||||
// 0b01111111 0b00111111
//
// I chose this over INC+JNZ because this will never
// overflow: it will just stay at zero.
shr byte ptr [esp + eax]
// No overflow means duplicate
jno .Lloop.duplicate
.Lloop.unique:
// *dst++ = AL
stosb byte ptr [edi], al
.Lloop.duplicate:
// Loop while there is still data
loop .Lloop
.Lloop.end:
// Clean up the stack and return.
// Note that sub esp, -128 is smaller than add esp, 128.
sub esp, -128
ret
char *.type_uniqchars(char *dst {edi}, const char *src {esi}, size_t len {eax})
srcis a pointer to the input stringdstis a pointer to an output buffer, it must be large enoughlenis the length ofsrcin bytes.
A pointer one byte past the end of the output string will be returned in edi. However, in the test code, I just null terminate because it is easier to print that way.
Doesn't follow standard calling convention, hence the leading dot.
Explanation (see comments for more)
This uses a lookup table on the stack, which is set to -1. It is 128 bytes because we are only dealing with ASCII.
Then, this magic is used:
shr byte ptr [esp + eax]
jno .Lloop.duplicate
This uses the fact that a one bit shr will put the most significant bit in the overflow flag. The first time, the overflow flag will be set since all bits are set, but then that most significant bit will be shifted out.
Unlike something like this:
inc byte ptr [esp + eax]
jnz .Lloop.duplicate
You could run this 1, 10, 100000 times, and it will never fail. That inc solution will fail after 256 duplicates as it wraps around to zero. Shifting right will just end up at zero and stay there indefinitely.
Other than that, it is a pretty straightforward string copy routine.
Pyth, 8 bytes
s.gxQk.|
- Bitwise Or the input
- Group the input by:
- It's index in the original input
- Join list and print.
Red, 23 bytes
func[s][union/case s s]
Using a map!, 58 bytes
func[s][m: copy #()foreach c s[put m c c]rejoin keys-of m]
A naive implementation, 69 bytes
func[s][rejoin collect[foreach c s[unless find collected c[keep c]]]]
K (ngn/k), 14 bytes
{x@&(!#x)=x?x}
A ngn/k implementation of the classic APL idiom for unique-ifying a list.
x?xfind the indices of the first time each character appears in the input(!#x)generate 0..n, where n is the length of the input(...)=...build boolean list storing whether or not the first index of each character in the input is the same as the index of each characterx@&filter input to the indices where the above is true
Jelly, 3 bytes
œ|/
Simply reduces by set union
Slightly more creative, but relies on "unique sieve" functions not being banned:
xŒQ
How it works
xŒQ - Main link. Takes a string S on the left
ŒQ - Unique sieve; For each character in S, replace it with 1 if it hasn't occurred yet, else 0
x - Repeat each character in S according to the corresponding value in the sieve
- Implicitly print, mashing empty strings into the output
Scala, 118114 bytes
def f(a:String):String=a.zipWithIndex.groupBy(_._1.toLower).map(_._2.head).toList.sortBy(_._2).map(_._1).mkString
05AB1E, 5 4 bytes
ʒkNQ
Try it online or verify all test cases.
Slightly more interesting previous 5 bytes version:
SkāαÏ
Try it online or verify all test cases.
Explanation:
ʒ # Filter the characters in the (implicit) input-string by:
k # Get the first index of the current character in the (implicit) input-string
NQ # Check if it's equal to the filter-index
# (after which the result is output implicitly)
S # Convert the (implicit) input-string to a list of characters
k # Get the first 0-based index of each character in the (implicit) input-string
ā # Push a list in the range [1, list-length] (without popping)
α # Get the absolute difference between the values at the same positions in the lists
Ï # Keep the characters of the (implicit) input-string at the truthy (==1) indices
# (after which the result is output implicitly)
With builtins allowed, this would of course be a single byte: Ù
Try it online or verify all test cases.
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.
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.
Python 3, 26 bytes
lambda s:[*dict(zip(s,s))]
Reviving an ancient question with a new idea, inspired by Noodle9's solution to "Special String reformatting" and my further refinement.
Because Python 3's dictionaries automatically remove duplicate keys beyond the first appearance while keeping them in order, we convert the the input string to a dictionary as keys. We then convert the dictionary back to a list with iterable unpacking, which extracts its keys. (The challenge seems to be fine with a list of characters in lieu of a string, asking for a "sequence of chars".)
While we could make the dictionary via a comprehension like {c:1for c in s}, it's one byte shorter to use the dict constructor as dict(zip(s,s)), which each character is both the key and the values. A same-length alternative is {}.fromkeys(s).
Note that while set does also remove duplicates, it fails to keep them in order, and is also disallowed by the challenge.
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.
Python, 62 bytes
lambda s:''.join([c for i,c in enumerate(s)if c not in s[:i]])
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|[])*""
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
R, 52 bytes
cat(union(a<-strsplit(readline(),"")[[1]],a),sep="")
Test examples:
Type uniqchars!
"I think'sdarloe,yu
3.14592687
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!
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>
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.
Octave, 25 bytes
@(s)s(sum(triu(s'==s))<2)
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.
Gema, 18 characters
?=${?;$0}@set{$0;}
Sample run:
bash-4.3$ gema '?=${?;$0}@set{$0;}' <<< 'hello world'
helo wrd
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
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
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
C, 47 bytes
a[];main(c){for(;read(0,&c,1);write(!a[c]++));}
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
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.
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
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.)
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()]))
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
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
Python 2, 62 bytes
s=set();print filter(lambda i:not(i in s or s.add(i)),input())
SED, 61 bytes
s/^/\a/
:
s/\a\(\(.\).*\)\2/\a\1/
t
s/\a\(.\)/\1\a/
t
s/\a//
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]);
}
}
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!
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.
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);
}
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
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.
Python 2, 42 bytes
Uses a couple anonymous functions and reduce.
lambda s:reduce(lambda x,y:x+y[y in x:],s)
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.
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[].
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).
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.
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.
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,0and 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,0and the check-for-duplicate loop counter is stored in1,0. - When a unique character is seen, it is stored on the first row, printed out, and the counter in
0,0is 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.
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".
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!'
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
><>, 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.
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
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;
}
Pyth, 7 bytes
soxzN{z
Pseudocode:
z = input
sum of order-by index in z of N over set of z.
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!
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.
Perl, 54 27 bytes
map{$h{$_}||=print}<>=~/./g
123456789012345678901234567
Test:
$ echo Type unique chars! | perl -e 'map{$h{$_}||=print}<>=~/./g'
Type uniqchars!
$
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.
Haskell, 50
f=concat.(tail>>=zipWith(\x y->[last x]\\y)).inits
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.
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 :)
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
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
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>
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/)
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.
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!"))
CJam, 3 bytes
qL|
Setwise or of the input with an empty list. CJam set operations preserve element order.

