Schreibe uniqchars!


41

Erstellen Sie bei einer Zeichenfolge aus druckbaren ASCII-Zeichen eine Ausgabe, die aus den eindeutigen Zeichen in der ursprünglichen Reihenfolge besteht . Mit anderen Worten, die Ausgabe ist dieselbe wie die Eingabe, mit der Ausnahme, dass ein Zeichen entfernt wird, wenn es zuvor aufgetreten ist.

Es können keine eingebauten Funktionen zum Auffinden eindeutiger Elemente in einem Array verwendet werden (MATLAB verfügt beispielsweise über eine uniqueFunktion, die dies ermöglicht). Die Idee ist, es manuell zu tun.

Weitere Details:

  • Es sind entweder Funktionen oder Programme erlaubt.
  • Die Ein- und Ausgabe kann in Form von Funktionsargumenten, stdin / stdout (auch für Funktionen) oder einer Mischung aus diesen erfolgen.
  • Wenn stdin oder stdout verwendet werden, wird eine Zeichenfolge als nur die verstandene Folge von Zeichen . Wenn Funktionsargumente verwendet werden, müssen die Folge von Zeichen kann sein eingeschlossen in Anführungszeichen oder eine gleichwertige Symbole , dass die Programmiersprache der Wahl Verwendungen für die Definition Saiten.
  • Die Ausgabe sollte eine Zeichenfolge sein, die nur die eindeutigen Zeichen der Eingabe enthält. Also keine zusätzlichen Zeilenumbrüche, Leerzeichen usw. Die einzige Ausnahme ist: Wenn die Ausgabe in stdout angezeigt wird, fügen die meisten Anzeigefunktionen ein Trailing hinzu \n(um die Zeichenfolge von der nächsten zu trennen). So ein nachlauf \nakzeptabel ist in stdout .
  • Stellen Sie nach Möglichkeit einen Link zu einem Online- Interpreter / -Compiler bereit, damit andere Ihren Code ausprobieren können.

Dies ist Codegolf , also gewinnt der kürzeste Code in Bytes.

Einige Beispiele unter der Annahme von stdin und stdout:

  1. Eingabezeichenfolge:

    Type unique chars!
    

    Ausgabezeichenfolge:

    Type uniqchars!
    
  2. Eingabezeichenfolge

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

    Ausgabezeichenfolge

    "I think'sdarloe,yu
    
  3. Eingabezeichenfolge

    3.1415926535897932384626433832795
    

    Ausgabezeichenfolge

    3.14592687
    

5
Nur um noch einmal zu überprüfen: Bedeutet die Regel no builtins, dass festgelegte Objekte nicht zulässig sind?
Sp3000

@ Sp3000 Festgelegte Objekte sind zulässig. Verwenden Sie nur keine Funktion oder Methode (falls vorhanden), die Ihnen ihre einzigartigen Elemente verleiht. Und Eingabe / Ausgabe sollten Zeichenfolgen sein, keine Objekte
Luis Mendo

@ Sp3000 Glaubst du, es wäre interessanter, die Byteanzahl um die Hälfte zu reduzieren, wenn keine festgelegten Funktionen verwendet werden? Oder besser nicht die Regeln ändern, sobald die Herausforderung festgelegt wurde?
Luis Mendo

5
Ich denke, dass derzeit nur meine Antwort Mengen verwendet, und es würde mir nichts ausmachen, wenn Sie sie ändern. Ich bin mir jedoch nicht sicher, ob sich ein solcher Bonus wirklich stark ändern würde, z. B. bezweifle ich, dass CJam in <6 Bytes ohne Sets möglich wäre. Ich bin mir auch nicht sicher, wo sich die Linie zwischen einem eingebauten Element, das eindeutige Elemente findet, und der Konstruktion einer Menge aus mehreren Elementen befindet ...
Sp3000

1
@ Sp3000 Ja, es ist eine unscharfe Grenze. Mit Set-Funktionen hatte ich nicht gerechnet. Ich denke, ich werde die Herausforderung so lassen, wie sie jetzt ist
Luis Mendo

Antworten:


13

GolfScript, 2 Bytes

.&

oder alternativ:

.|

Ich habe dies vor einiger Zeit in den Golftipps im GolfScript- Thread gepostet . Dies funktioniert, indem Sie die Eingabezeichenfolge (die vom GolfScript-Interpreter automatisch auf den Stapel gelegt wird und sich in den meisten Fällen wie ein Array von Zeichen verhält) duplizieren und dann die festgelegte Schnittmenge ( &) oder Vereinigung ( |) mit sich selbst vornehmen . Durch das Anwenden eines Mengenoperators auf ein Array (oder eine Zeichenfolge) werden alle Duplikate reduziert, die Reihenfolge der Elemente bleibt jedoch erhalten.


23

CJam, 3 Bytes

qL|

Setwise oder von der Eingabe mit einer leeren Liste. CJam-Set-Operationen behalten die Elementreihenfolge bei.

Probieren Sie es online aus


Ich gehe davon aus, dass dies gültig ist, da Sätze zulässig sind, aber ich bin nicht sicher ...
Sp3000

Sehr schlau! Ich wusste, dass CJam einer der besten sein würde, aber ich habe nicht nur 3 Bytes erwartet!
Luis Mendo

19

C # 6, 18 + 67 = 85 Bytes

Benötigt diese usingAussage:

using System.Linq;

Die eigentliche Methode:

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

Diese Methode spart einige Zeichen, indem sie die Funktion als Lambda definiert , was in C # 6 unterstützt wird. So würde es in C # vor 6 aussehen (aber ungolfed):

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

So funktioniert es: Ich rufe die WhereMethode für den String mit einem Lambda mit zwei Argumenten auf: xRepräsentation des aktuellen Elements, iRepräsentation des Index dieses Elements. IndexOfGibt immer den ersten Index des übergebenen Zeichens zurück. Wenn dieser ialso nicht dem ersten Index von entspricht x, handelt es sich um ein doppeltes Zeichen, das nicht enthalten sein darf.


3
Ich hätte ehrlich gesagt nicht erwartet, dass C # so kurz ist. Exzellente Arbeit!
Alex A.

Ähm. Ich denke, Sie sollten ein vollständiges Programm (mit static void Mainusw.) einreichen .
Timwi

3
@Timwi Diese Abfrage besagt, dass entweder Funktionen oder Programme zulässig sind.
HDV

C # ermöglicht einen kürzeren Ansatz, auch unter Verwendung von LINQ. Ich habe eine konkurrierende Antwort gepostet. :)
hvd

@hvd Schöne! +1
ProgramFOX

14

Retina , 14 Bytes

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

Jede Zeile sollte in einer eigenen Datei abgelegt sein, oder Sie können das -sFlag verwenden, um aus einer Datei zu lesen.

Um es zu erklären, verwenden wir diese längere, aber einfachere Version:

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

Die erste Zeile ist die Regex, mit der abgeglichen werden soll ( +`ist die Konfigurationszeichenfolge, die so lange ausgeführt wird, bis alle Ersetzungen vorgenommen wurden). Die Regex sucht nach einem Zeichen (wir nennen es C), gefolgt von null oder mehr beliebigen Zeichen, gefolgt von C. Die Klammern bezeichnen Erfassungsgruppen, also ersetzen wir die Übereinstimmung mit C ( $1) und den Zeichen dazwischen ( $2). Entfernen des Duplikats von C.

Zum Beispiel, wenn die Eingabezeichenfolge war uniquewürde, der erste Lauf entspricht uniqu, mit uund niqwie $1und $2dargestellt. Es würde dann den übereinstimmenden Teilstring in der ursprünglichen Eingabe durch uniq, giving ersetzen uniqe.


3
Ich suchte nach einem Regex, um dies zu tun; Ich wusste nicht, dass es so kurz ist! +1
ETHproductions

13

Perl, 21 (20 Bytes + -p)

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

Verwendungszweck:

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

1
Sie könnten das Negieren von 1 Byte speichern $h{$&}und ein logisches UND anstelle eines ternären Operators verwenden:s/./!$h{$&}++&&$&/eg
kos

@kos Wenn du mich gefragt hättest, hätte ich dir gesagt, dass ich dies zu 100% versucht habe und am Ende 1s in der Ausgabe habe, aber das ist nicht der Fall! Vielen Dank für die Aktualisierung!
Dom Hastings

1
Upvoted already :) Ich glaube, du hast es versucht s/./$h{$&}++||$&/eg(auch darauf bin ich zuerst hereingefallen ). Schade, denn das wäre ein weiteres gespeichertes Byte gewesen.
Kos

11

Makkaroni 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
  • Erstellen Sie eine "Anti-Golf" -Sprache: Überprüfen Sie
  • golf es trotzdem: check

Dies ist ein vollständiges Programm, das Eingaben von STDIN und Ausgaben von STDOUT ausführt.

Umwickelte Version, für ästhetischen Wert:

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

Und eine stark "kommentierte" und ungolfederte Version (es gibt keine Kommentare in Macaroni, daher verwende ich nur bloße String-Literale):

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

(Dies ist das erste echte Makkaroni-Programm (das tatsächlich etwas tut)! \ O /)


5
• Geben Sie der Sprache einen lustigen und passenden Namen: check
Luis Mendo

11

JavaScript ES7, 37 33 25 Bytes

Ziemlich einfacher Ansatz unter Verwendung des Spread-Operators für das Verständnis vonSet ES6- und ES7- Arrays :

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

22 Bytes weniger als der indexOfAnsatz. Arbeitete an einer Handvoll Testfällen.


Die Räume um for‚s Ausdruck sind nicht notwendig und man könnte es anonyme Funktion machen wie einige andere Lösungen tat s=>[for(c of Set(s))c].join``. (Blasses Update: nicht 100% sicher, aber das newSchlüsselwort scheint auch unnötig.)
Manatwork

Ich war mir nicht sicher, welche Regeln es für anon-Funktionen gibt und wie gut der Platz ist.
Azz

Transpilierter Code ohne newErgebnis Uncaught TypeError: Constructor Set requires 'new'in Google Chrome.
Azz

Entschuldigen Sie bitte meine Unwissenheit, aber an welchem ​​Punkt filtert dieser Filter eindeutige Werte? Es sieht so aus, als würde nur eine Zeichenfolge in eine Menge in ein Array konvertiert und dann die Werte wieder zu der ursprünglichen Zeichenfolge verknüpft.
Patrick Roberts

@PatrickRoberts es ist die Umwandlung in eine Menge. Ein Satz per Definition hat keine Duplikate
edc65

8

C # 6 - 18 + 46 = 64

using System.Linq;

und dann

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

Die Enumerable.UnionErweiterungsmethode gibt an, dass Elemente in der ursprünglichen Reihenfolge zurückgegeben werden:

Wenn das von dieser Methode zurückgegebene Objekt aufgelistet wird, listet Union die ersten und zweiten Elemente in dieser Reihenfolge auf und gibt jedes Element aus, das noch nicht ausgegeben wurde.

Festlegen von Vorgängen, die nicht speziell zum Auffinden eindeutiger Werte vorgesehen sind, scheint nach den anderen Antworten beurteilt zu werden.


Nizza, dachte ich, string u(string s)=>String.Join("",s.Distinct());aber das ist ein bisschen länger.
Germi

@germi Danke. Es wurde bereits eine Antwort mit verwendet Distinct(), diese wurde jedoch gelöscht, da sie Distinct()in dieser Herausforderung nicht zulässig ist, da es sich um eine Methode handelt, mit der eindeutige Werte ermittelt werden sollen.
HDV

Ah richtig ... das bisschen übersehen;)
Germi

Ist s => string.Concat(s.Union(s))gültig? Das würde der Delegierte Func<string, string>als Argument an a weitergeben.
Tyler StandishMan

@TylerStandishMan Wenn das zutrifft, würde ich erwarten, dass mehr Leute davon Gebrauch machen, und ich habe es noch nie gesehen, also glaube ich nicht, dass es das ist. Aber vielleicht sollte es gültig sein - dies scheint es wert zu sein, nach Meta zu suchen, wenn Sie interessiert sind.
HDV

7

JavaScript ES6, 47 Bytes

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

Der folgende Test funktioniert auf allen Browsern.

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>


Was macht das <i?'':eTeil?
DanTheMan

1
Es ist ein ternärer Operator. Befindet sich die erste Instanz eines Zeichens evor dem aktuellen Index i, wird eine leere Zeichenfolge zurückgegeben, wodurch das Zeichen entfernt wird. Wenn dies die erste Instanz ist, wird sie einfach zurückgegeben eund es werden keine Änderungen vorgenommen.
NinjaBearMonkey

7

MATLAB, 23

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

Führt die "Vereinigung" der Eingabezeichenfolge mit sich selbst aus, verwendet die "Stable" -Methode, sortiert nicht und druckt dann.

Dies funktioniert, da unionnach dem Zusammenführen nur nicht doppelte Werte zurückgegeben werden. Wenn Sie also im Wesentlichen uniondie Zeichenfolge mit sich selbst verwenden, wird zunächst eine Zeichenfolge wie erzeugt Type unique chars!Type unique chars!, und anschließend werden alle Duplikate ohne Sortieren entfernt.

Keine Notwendigkeit für unique:)


uniquenicht erlaubt, sorry! Es ist in der Herausforderung Definition
Luis Mendo

Das habe ich verpasst, egal.
Tom Carpenter

Darf ich nach der Antwort von Sp3000 setdiffdie 'stable'Option vorschlagen ?
Luis Mendo

1
Nett! Und ja, Sie können entfernen, dispweil Sie dann eine Funktion haben, die eine Zeichenfolge zurückgibt, die zulässig ist
Luis Mendo

1
Sie können auch intersectmit verwenden 'stable', um den gleichen Effekt zu erzielen. Ich wollte das schreiben, aber angesichts dieser Antwort ist es nicht mehr original lol.
rayryeng - Wiedereinsetzung von Monica

7

> <> , 16 Bytes

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

> <> hat keine Zeichenketten, daher verwenden wir die Codebox. Aufgrund der Ringform von> <> läuft Folgendes in einer Schleife ab:

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

Beachten Sie, dass dies die Tatsache nutzt, dass die Eingabe nur druckbares ASCII enthält, da dies nicht funktionieren würde, wenn ASCII 0 vorhanden wäre.


1
.......das ist brilliant. Ich wünschte, ich hätte daran gedacht. Ich werde eine Befunge-Version davon in meine Antwort aufnehmen, aber nicht als primäre. EDIT: Beim zweiten Gedanken würde dies nicht funktionieren, da Befunge keinen unendlichen Code-Raum hat. Dangit!
El'endia Starman

@ El'endiaStarman Ich denke , die Beam - Antwort auch die gleiche Sache tut, so kann ich leider ich zuerst nicht sagen war: P
SP3000

Ahh, ja, ich denke du hast recht. Ihre Erklärung ist jedoch klarer.
El'endia Starman


5

Element , 22 19 18 Bytes

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

Beispiel Ein- / Ausgabe: hello world->helo wrd

Dies funktioniert, indem Sie die Zeichenfolge einfach zeichenweise verarbeiten und nachverfolgen, welche zuvor gesehen wurden.

_'{"(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


4

Python 3, 44

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

Erstellt die Ausgabezeichenfolge zeichenweise r, einschließlich des Zeichens caus der Eingabe, sofern wir es noch nicht gesehen haben.

Python 2 wäre 47, verliert 4 Zeichen raw_inputund spart 1, wenn keine Parer benötigt werden print.


Der Konsens scheint nun zu sein, dass Sie inputin Python 2 verwenden können, sodass Sie Ihr Byte kürzer machen können.
mbomb007

4

APL, 3

∊∪/

Dies wendet die Vereinigung (∪) zwischen jedem Element des Vektors an, wodurch eine Iteration erhalten wird, die das Entfernen von Duplikaten bewirkt.

Teste es auf tryapl.org

Altes:

~⍨\

Dies verwendet ~ (mit umgekehrten Argumenten, mit ⍨), das zwischen den einzelnen Elementen des Arguments angewendet wird. Das Ergebnis ist, dass für jedes Element, wenn es bereits in der Liste enthalten ist, es gelöscht wird.


Nitpicking: "Und Input / Output sollten Strings sein", sagt Luis. "Unione Reduce" gibt ein verschachteltes Array zurück, keine Zeichenfolge. O :-)
lstefano

Sie haben Recht und fügen am Anfang ein ∊ hinzu, um die Korrektur durchzuführen.
Moris Zucca

3

Perl, 54 27 Bytes

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

Prüfung:

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

1
print exists($h{$_})?"":$_$h{$_}||print
manatwork

Hat SO ein Unicode → Zeichen eingefügt, das es kaputt macht?
Steve

1
Wenn Sie einen Anweisungsmodifikator verwenden, sparen Sie einige Bytes, zusammen mit dem Vorschlag von @ manatwork, $h{$_}||=printund <>=~/./gwenn Sie verwenden, sparen Sie auch ein paar weitere Bytes !
Dom Hastings

1
Nein, ich habe es eingefügt, mit der Bedeutung von "Ändern zu".
Manatwork

1
Ein Wechsel zu mapwürde auch die Ersparnis verbessern: map{$h{$_}||=print}<>=~/./g
manatwork

3

PHP, 72 Bytes 84 Bytes

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

Verwendet die Zeichen als Schlüssel für ein assoziatives Array und druckt die Schlüssel aus. Die Reihenfolge der Array-Elemente ist immer die Reihenfolge der Einfügung.

Danke Ismael Miguel für den str_splitVorschlag.


1
<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a));Kürzere und macht das gleiche.
Ismael Miguel

Gefunden eine kürzere Schleife: while($c=$argv[1][$i++*1]). Dies ersetzt das Ganze foreach. Alles andere ist das gleiche
Ismael Miguel

Ich habe zuerst etwas Ähnliches ausprobiert, aber darauf verzichtet, weil es bei einem Zeichen aufhören würde, das zu "falsch" zwingt, d "0". H. Versuchen Sie "abc0def" als Eingabe.
Fabian Schmengler

Da hast du recht. Sicher gibt es eine Problemumgehung, die nicht mehr als 2 Byte kostet.
Ismael Miguel

3

Pyth, 7 Bytes

soxzN{z

Pseudocode:

z = Eingabe

Summe des Ordnungsindex in z von N über der Menge von z.


3

Julia, 45 42 Bytes

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

Alte Version:

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

Code erstellt die neue Zeichenfolge, indem er neue Zeichen anfügt und sie joinam Ende zu einer richtigen Zeichenfolge zusammenfügt. Die neue Version spart einige Zeichen, indem sie über das Array-Verständnis iteriert. Spart auch ein Byte durch Verwendung von ?:anstatt ||(da keine eckigen Klammern um die Zuweisung erforderlich sind).

Alternative Lösung, 45 Byte, unter Verwendung von Rekursion und Regex:

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

Julia, 17 Bytes

(Alternative Version)

s->join(union(s))

Dies dient unionim Grunde genommen als Ersatz für unique- ich betrachte dies nicht als die "echte" Antwort, da ich "nicht verwenden unique" so interpretiere , dass "keine einzige integrierte Funktion verwendet wird, die den Effekt hat, das Eindeutige zurückzugeben Elemente ".


Ich hatte eine ähnliche Idee, aber sie war nicht so präzise. Gute Arbeit!
Alex A.

3

Java, 78 Bytes

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

Eine einfache Schleife, während die Ausgabe auf bereits vorhandene Zeichen überprüft wird. Akzeptiert Eingaben als char[].


3

C 96 Bytes

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

Dies verwendet ein Array von Ganzzahlen, die durch die ASCII-Zeichennummer indiziert sind. Die Zeichen werden nur gedruckt, wenn diese Stelle im Array auf FALSE gesetzt ist. Nachdem jedes neue Zeichen gefunden wurde, wird diese Stelle im Array auf TRUE gesetzt. Dies übernimmt eine Textzeile aus der Standardeingabe, die durch eine neue Zeile abgeschlossen wird. Nicht-ASCII-Zeichen werden ignoriert.


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

3

C - 58

Vielen Dank an @hvd und @AShelly für das Speichern einiger Zeichen. Es wurden mehrere Möglichkeiten vorgeschlagen, um es viel kürzer als das Original zu machen:

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

Wie Sie sehen können, scheint die Änderung an Ort und Stelle die kürzeste (bisher!) Zu sein. Das Testprogramm wird ohne Warnung mit kompiliert 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
}

Danke für all die Hilfe. Ich schätze all die Ratschläge, die gegeben wurden, um so viel zu verkürzen!


Nun, da bereits der Code nicht gültig C ist, akzeptiert nur durch milde C Compiler: Sie können erklären , rwie int(und lassen die int) einige Bytes speichern: f(s,r)char*s;{...}. Aber es beschränkt Ihren Code auf Plattformen mit char*der gleichen Größe wie intund natürlich mit Compilern, die so nachsichtig sind wie Ihre und meine.
HDV

@hvd Das ist böse! Ich war bereit, den Rückgabewert als Standard festzulegen, da ich ihn nicht verwende. Aber das ist ein bisschen zwielichtiger als ich es gerne wäre. Ich denke, ich würde es vorziehen, es konform zu machen, anstatt so weit zu gehen! Danke, dass du wieder auf die helle Seite gekommen bist.
Jerry Jeremiah

Sie können durch das Ersetzen eines char speichern if(x)ymitx?y:0
ugoren

Hier ist eine 60-Zeichen-Funktion, die anstelle eines Array-Parameters in stdout schreibt: f(char*s){int a[128]={0};for(;*s;s++)a[*s]++?0:putchar(*s);}
AShelly

Sie können kopieren bedingungslos in *q, und nur erhöhen , qwenn der Charakter früher erschienen, so dass zusammen mehr etwas Füllung: void f(char*s,char*r){for(char*q=r;*q=*s;strchr(r,*s++)<q||q++);}(Beachten Sie, dass strchr(r,*s++)<qimmer gut definiert ist, gibt es keinen gibt UB, weil strchrnicht zurückkehren kann NULLin dieser Version.) Mit Ausnahme des Rückgabetyp, Es ist sogar kürzer als die Version von @ AShelly.
HDV 06.10.15

2

Ruby, 30 24 Zeichen

(23 Zeichen Code + 1 Zeichen Befehlszeilenoption.)

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

Probelauf:

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

2

CJam, 9

Lq{1$-+}/

Dadurch wird keine Zeichenfolge in eine Menge konvertiert, sondern es wird eine Art Mengenunterschied ausgeführt, um zu bestimmen, ob ein Zeichen in einer Zeichenfolge gefunden wird. Probieren Sie es online aus

Erläuterung:

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

Eine andere Version, 13 Bytes:

Lq{_2$#)!*+}/

Dies hat nichts mit Mengen zu tun. Probieren Sie es online aus

Erläuterung:

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

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

Die Gleichungsvariablen sind selten nützlich, da sie 5 Bytes benötigen, um gespeichert zu werden. Sie sind hier jedoch nützlich, da sie Y₁das Xdritte Zeichen der Zeichenfolge sind und 3 Bytes einsparen. Da wir in TI-BASIC keine leeren Zeichenfolgen hinzufügen können, beginnen wir die Zeichenfolge mit dem ersten Zeichen von Str1, durchlaufen dann den Rest der Zeichenfolge und fügen alle Zeichen hinzu, die noch nicht vorhanden sind.

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

2

Matlab, 46 Bytes

Es verwendet eine anonyme Funktion mit Funktionsargumenten als Ein- und Ausgabe:

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

(In einem Octave-Online-Dolmetscher funktionierte das nicht.)

Beispiel Verwendung:

>> @(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!

das wäre auch meine idee gewesen :) - das brauchst du übrigens nicht ,1mit any.
Jonas

@ Jonas Danke! Obwohl es schwer ist, durch dieses Durcheinander von Klammern zu kommen, 1ist das für triu (ich muss die Diagonale entfernen), nicht fürany
Luis Mendo

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

Testen Sie es in diesem Online-Dolmetscher .


Das war schwieriger als ich erwartet hatte. Ich werde morgen eine ausführlichere Erklärung veröffentlichen, wenn jemand dies wünscht, aber hier ist eine Übersicht über die Funktionen meines Codes.

  • Bisher gesehene eindeutige Zeichen werden in der ersten Reihe gespeichert, beginnend von 2,0und bis nach rechts. Dies wird überprüft, um festzustellen, ob das aktuelle Zeichen ein Duplikat ist.
  • Die Anzahl der bisher gesehenen eindeutigen Zeichen wird in gespeichert, 0,0und der Zähler für die Prüfung auf Duplikate wird in gespeichert 1,0.
  • Wenn ein eindeutiges Zeichen angezeigt wird, wird es in der ersten Zeile gespeichert, ausgedruckt und der Zählerstand 0,0erhöht.
  • Um Probleme beim Lesen in den vorhandenen Leerzeichen (ASCII 32) zu vermeiden, setze ich das Zeichen, das -1 (wirklich 65536) entspricht, in den nächsten Steckplatz für das nächste eindeutige Zeichen.

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

Wenn Sie die Antwort von @ fschmengler in der array_flipVersion mit zwei Sekunden ausschneiden, wird eine variable Methode verwendet. Dabei wird die Zeichenfolge in true umgewandelt, in false negiert und anschließend in die leere Zeichenfolge im ersten Argument zurückgeschrieben, um ein paar Bytes in der zweiten zu speichern. Billig!


2

Haskell , 29 Bytes

Verschachtelbarer Einzeiler ohne variablen Namen:

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

Dieselbe Anzahl, gespeichert in einer Funktion, die fals Deklaration der obersten Ebene bezeichnet wird:

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

Beachten Sie, dass es eine geringfügig betrügerische Optimierung gibt, die ich im Geiste der Freundlichkeit nicht vorgenommen habe: Nach den Regeln dieser Herausforderung ist es technisch immer noch zulässig, eine andere Eingabe- und Ausgabecodierung für eine Zeichenfolge zu verwenden. Durch die Darstellung einer stringvon der Kirche teilweise angewendeten Codierung \f -> foldr f [] string :: (a -> [b] -> [b]) -> [b](mit der anderen Seite der durch die Funktion bereitgestellten Bijektion ($ (:))) werden ($ \x->(x:).filter(x/=))nur 24 Zeichen abgegolft .

Ich habe es vermieden, die 24- foldr(\x->(x:).filter(x/=))[]"Type unique chars!"stellige Antwort als meine offizielle Antwort zu veröffentlichen, da die obige Lösung auf dem obigen Interpreter ausprobiert werden könnte, während stattdessen die Golf-Lösung geschrieben würde:

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

als Abkürzung für die wörtliche Erklärung, die verrückter wäre:

($ \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[]

Aber es ist eine vollkommen gültige Version der Datenstruktur, die als reine Funktionen dargestellt wird. (Natürlich können Sie auch verwenden \f -> foldr f [] "Type unique chars!", aber das ist vermutlich unzulässig, da es Listen verwendet, um die Daten tatsächlich zu speichern. Daher sollte sein Foldr-Teil vermutlich in die "Antwort" -Funktion zusammengesetzt werden, was zu mehr als 24 Zeichen führt.)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.