Введіть uniqchars!


41

З огляду на рядок, що складається з символів для друку ASCII , створіть результат, що складається з його унікальних символів у вихідному порядку . Іншими словами, вихід є таким же, як і вхід, за винятком того, що знак видаляється, якщо він з'явився раніше.

Жодні вбудовані для пошуку унікальних елементів у масиві не можна використовувати (наприклад, MATLAB має uniqueфункцію, яка це робить). Ідея - це зробити вручну.

Детальніше:

  • Будь-які функції або програми дозволені.
  • Введення та вихід можуть бути у вигляді аргументів функції, stdin / stdout (навіть для функцій) або поєднання цих.
  • Якщо використовується stdin або stdout, рядок розуміється як лише послідовність символів . Якщо використовуються аргументи функції, послідовність символів може бути потребна укласти в лапки або еквівалентні символи, які мова вибору програмування використовує для визначення рядків.
  • Вихід повинен бути рядком, що містить лише унікальні символи вводу. Тому немає зайвих розривів рядків, пробілів і т. Д. Єдиним винятком є: якщо висновок відображається в stdout, більшість функцій відображення додають трейлінг \n(щоб відокремити рядок від наступного). Таким чином, один трейлінг \nє прийнятним у stdout .
  • Якщо можливо, опублікуйте посилання на онлайн- перекладача / компілятора, щоб інші могли спробувати ваш код.

Це код гольфу , тому найкоротший код у байтах виграє.

Деякі приклади , припускаючи stdin та stdout:

  1. Рядок введення:

    Type unique chars!
    

    Вихідний рядок:

    Type uniqchars!
    
  2. Рядок введення

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

    Вихідний рядок

    "I think'sdarloe,yu
    
  3. Рядок введення

    3.1415926535897932384626433832795
    

    Вихідний рядок

    3.14592687
    

5
Для подвійної перевірки: чи означає правило noinsins, що встановлені об'єкти заборонені?
Sp3000

@ Sp3000 Встановити об'єкти дозволено. Просто не використовуйте функцію чи метод (якщо він існує), який дає вам унікальні елементи. І введення / вихід повинен бути рядками, а не встановленими об'єктами
Luis

@ Sp3000 Як ви вважаєте, було б цікавіше зменшити кількість байтів вдвічі, якщо не використовуються задані функції? Або краще не змінювати правила, як тільки завдання було встановлено?
Луїс Мендо

5
Я думаю, що лише моя відповідь використовує набори в даний час, і я не заперечував би, якщо ви її змінили. Однак я не дуже впевнений, що подібний бонус значно зміниться, наприклад, я сумніваюся, що CJam був би можливим у <6 байт без наборів. Крім того, я не впевнений, де знаходиться лінія між вбудованим, який знаходить унікальні елементи, та побудовою набору з ряду елементів ...
Sp3000

1
@ Sp3000 Так, це розмита межа. Я не очікував встановлення функцій. Думаю, я вийду з виклику, як зараз
Луїс Мендо

Відповіді:


13

GolfScript, 2 байти

.&

або, альтернативно:

.|

Я розмістив це деякий час тому в Радах щодо гольфу в потоці GolfScript . Він працює шляхом дублювання вхідного рядка (який автоматично ставиться на стек інтерпретатором GolfScript і який веде себе в більшості способів, як масив символів), а потім приймає встановлений перетин ( &) або об'єднання ( |) із собою. Застосування оператора набору до масиву (або рядка) згортає будь-які дублікати, але зберігає порядок елементів.


23

CJam, 3 байти

qL|

Встановити або ввести з порожнім списком. Операції з набору CJam зберігають порядок елементів.

Спробуйте в Інтернеті


Я припускаю, що це дійсно, оскільки набори дозволені, але я не впевнений ...
Sp3000

Дуже розумний! Я знав, що CJam буде одним з найкращих, але не очікував лише 3 байти!
Луїс Мендо

19

C # 6, 18 + 67 = 85 байт

Потрібна ця usingзаява:

using System.Linq;

Фактичний метод:

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

Цей метод економить деякі символи, визначаючи функцію як лямбда , яка підтримується в C # 6. Ось як це виглядатиме в C # pre-6 (але без заготівлі):

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

Як це працює: я називаю Whereметод на рядку лямбда з двома аргументами: xпредставляє поточний елемент, iпредставляє індекс цього елемента. IndexOfзавжди повертає перший індекс передаваного йому знаку, тому, якщо iвін не дорівнює першому індексу x, це дублікат char і не повинен включатися.


3
Я, чесно, не очікував, що C # буде таким коротким. Відмінна робота!
Олексій А.

Ум. Я думаю, ви повинні подати повну програму (з static void Mainтощо).
Тімві

3
@Timwi У цьому виклику зазначено "Дозволені або функції, або програми."
hvd

C # дозволяє скоротити підхід, також використовуючи LINQ. Я опублікував конкуруючу відповідь. :)
hvd

@hvd Приємний! +1
ProgramFOX

14

Сітківка , 14 байт

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

Кожен рядок повинен містити свій окремий файл, або ви можете використовувати -sпрапор для читання з одного файлу.

Щоб пояснити це, ми будемо використовувати цю довшу, але простішу версію:

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

Перший рядок - це регулярний вирівнювання ( +`це рядок конфігурації, який продовжує працювати, поки не будуть виконані всі заміни). Режекс шукає символ (ми будемо називати його C), за ним - нуль або більше довільних символів, а потім C. Дужки позначають групи захоплення, тому ми замінюємо збіг на C ( $1) та символи між ( $2), вилучення дубліката С.

Наприклад, якщо вхідний рядок була unique, перший запуск буде відповідати uniqu, з uі , niqяк $1і $2, відповідно. Потім він замінить відповідна підрядку в початковому вході на uniq, даючи uniqe.


3
Я шукав режекс для цього; Я не усвідомлював, що це так коротко! +1
ETHproductions

13

Perl, 21 (20 байт + -p)

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

Використання:

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

1
Ви можете зберегти 1 байт, заперечуючи $h{$&}та використовуючи логіку AND, а не потрійний оператор:s/./!$h{$&}++&&$&/eg
kos

@kos якби ти запитав мене, я б сказав тобі, що я на 100% спробував це і закінчився 1s у виході, але це не так! Дякую, оновлення!
Дом Гастінгс

1
Оновлено вже :) Я думаю, що ви спробували s/./$h{$&}++||$&/eg(я впав і для цього спочатку). Сором, бо це був би ще один збережений байт.
kos

11

Макарони 0,0,2 , 233 байт

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
  • створити мову "проти гольфу": перевірити
  • гольф все одно: перевірити

Це повна програма, яка вводить дані STDIN та виводить на STDOUT.

Загорнута версія, для естетичної цінності:

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

І сильно "коментована" і неперевершена версія (в Macaroni немає коментарів, тому я просто використовую голі рядкові літерали):

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

(Це перша реальна програма Macaroni (яка насправді щось робить)! \ O /)


5
• дайте мові смішну та відповідну назву: перевірка
Луїс Мендо

11

JavaScript ES7, 37 33 25 байт

Досить простий підхід із використанням операторів поширення розуміння масивів ES6 Setта ES7 Array :

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

На 22 байти менше, ніж indexOfпідхід. Працював над кількома тестовими кейсами.


Проміжки навколо for виразу «S не потрібні , і ви могли б зробити це анонімна функція як і деякі інші рішення: s=>[for(c of Set(s))c].join``. (Блідне оновлення: не на 100% впевнений, але newключове слово здається також непотрібним.)
манатура

Не був упевнений у правилах із функціями анон та гарним захопленням місця.
azz

Транспільований код без newрезультатів роботи Uncaught TypeError: Constructor Set requires 'new'в Google Chrome.
azz

Вибачте, будь ласка, про моє незнання, але в який момент цей фільтр унікальних значень? Схоже, що він просто перетворює рядок у набір до масиву, а потім приєднується до значень, що призводить до початкового рядка знову.
Патрік Робертс

@PatrickRoberts - це перетворення на набір. Набір за визначенням не має дублікатів
edc65

8

C # 6 - 18 + 46 = 64

using System.Linq;

і потім

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

Метод Enumerable.Unionрозширення вказує, що елементи повертаються в початковому порядку:

Коли об'єкт, повернутий цим методом, перераховується, Union перераховує перше і друге в тому порядку і виводить кожен елемент, який ще не був виведений.

Встановити операції, які спеціально не призначені для пошуку унікальних значень, схоже, дозволяється судити за іншими відповідями.


Хороший, я думав, string u(string s)=>String.Join("",s.Distinct());але це трохи довше.
гермі

@germi Дякую Відповідь Distinct()вже використано , але її видалено, оскільки Distinct()заборонено в цьому виклику, оскільки це метод, призначений спеціально для пошуку унікальних значень.
hvd

Ага ...
переглянув

Чи s => string.Concat(s.Union(s))дійсно? Це був би делегат, переданий Func<string, string>як аргумент.
Тайлер StandishMan

@TylerStandishMan Якщо це дійсно, я б очікував, що більше людей скористається ним, і я цього раніше не бачив, тому не думаю, що це так. Але, можливо, це має бути дійсним - це здається чимось вартим перевірки на Meta, якщо ви зацікавлені.
hvd

7

JavaScript ES6, 47 байт

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

Нижче наведений тест працює на всіх браузерах.

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>


Що робить <i?'':eчастина?
DanTheMan

1
Це потрійний оператор. Якщо перший екземпляр символу eзнаходиться перед поточним індексом i, він повертає порожню рядок, таким чином позбавляючись від символу. Якщо це перший екземпляр, він просто повертається eі жодних змін не вноситься.
NinjaBearMonkey

7

МАТЛАБ, 23

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

Чи "встановлює об'єднання" вхідного рядка з собою, використовуючи метод "стабільний", який не сортує, а потім друкує.

Це працює, тому що unionповертає лише не повторювані значення після об'єднання. Тож по суті, якщо ви unionвикористовуєте рядок із собою, він спочатку створює рядок якType unique chars!Type unique chars! , а потім видаляє всі дублікати без сортування.

Не потрібно unique:)


uniqueне дозволено, вибачте! Це у визначенні виклику
Луїс Мендо

Пропустив це, неважливо.
Том Карпентер

Після відповіді Sp3000, в я можу запропонувати setdiffз 'stable'варіантом?
Луїс Мендо

1
Приємно! І так, ви можете видалити, dispтому що тоді у вас є функція, яка повертає рядок, яка дозволена
Luis Mendo

1
Ви також можете використовувати intersectз, 'stable'щоб досягти такого ж ефекту. Я збирався це написати, але, з огляду на цю відповідь, це вже не оригінальний лол.
rayryeng

7

> <> , 16 байт

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

> <> не має рядків, тому ми використовуємо кодовий ящик. Через тороїдальну природу> <>, цикл виконує наступні дії:

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

Зауважте, що для цього використовується той факт, що вхід містить тільки друкований ASCII, оскільки це не працює, якби був присутній ASCII 0.


1
....... це геніально. Я б хотів, щоб я про це подумав. Я включу у свою відповідь версію Befunge, але не як основну. EDIT: По-друге, це не спрацює, оскільки Befunge не має нескінченного простору коду. Dangit!
El'endia Starman

@ El'endiaStarman Я думаю, що відповідь Біма також робить те саме, тому, на жаль, я не можу сказати, що я був першим: P
Sp3000

Ага, так, я думаю, ти маєш рацію. Однак ваше пояснення зрозуміліше.
El'endia Starman


5

Елемент , 22 19 18 байт

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

Приклад введення / виводу: hello world->helo wrd

Це працює, просто обробляючи рядок один символ за часом і відстежуючи, які з них вони бачили раніше.

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

Пітон 3, 44

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

Побудовує вихідний рядок rза символом, включаючи символ cіз вхідних даних, лише якщо ми цього ще не бачили.

Python 2 був би 47, втративши 4 символи raw_inputта заощадивши 1 на не потрібних парушках для print.


Зараз, мабуть, існує думка, що ви можете використовувати inputв Python 2, тому ви можете зробити свій байт коротшим.
mbomb007

4

APL, 3

∊∪/

Це стосується об'єднання (∪) між кожним елементом вектора, отримуючи ітерацію, що має ефект видалення дублікатів.

Перевірте це на tryapl.org

Старий:

~⍨\

Для цього використовується ~ (із зворотними аргументами, використовуючи ⍨), застосований між кожним елементом аргументу. Результат полягає в тому, що для кожного елемента, якщо він вже є у списку, він стирається.


Нітчікінг: "І введення / вихід повинен бути рядками", - каже Луїс. "Unione smanjenje" повертає вкладений масив, а не рядок. O :-)
lstefano

Ви праві, додавши, на початку, щоб виправити.
Моріс Зукка

3

Perl, 54 27 байт

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

Тест:

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

1
print exists($h{$_})?"":$_$h{$_}||print
манатура

Чи ТАК вставив унікод → char у рендеринг, який відображається порушеним?
Стів

1
використання модифікатора оператора допоможе вам заощадити кілька байтів, а також пропозиції @ manatwork, $h{$_}||=printа використання <>=~/./gтакож допоможе зберегти ще кілька!
Дом Гастінгс

1
Ні, я вставив його зі значенням "змінити на".
манатура

1
Зміни на mapполіпшить також заощадження: map{$h{$_}||=print}<>=~/./g
маніпулювання

3

PHP, 72 байти 84 байт

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

Використовує символи як ключі для асоціативного масиву, а потім роздруковує клавіші. Порядок елементів масиву - це завжди порядок вставки.

Дякую Ісмаелю Мігелю за str_splitпропозицію.


1
<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a));Коротше і робить те ж саме.
Ісмаїл Мігель

Знайдено коротший цикл: while($c=$argv[1][$i++*1]). Це замінює ціле foreach. Все інше те саме
Ісмаїл Мігель

Я спробував щось подібне спочатку, але утримався від нього, оскільки це зупиниться на персонажі, який примушує до "помилкового", тобто "0". Спробуйте "abc0def" як вхід.
Фабіан Шменглер

Ти в цьому прав. Звичайно, для цього є рішення, яке не коштуватиме більше 2 байт.
Ісмаїл Мігель

3

Pyth, 7 байт

soxzN{z

Псевдокод:

z = вхід

сума впорядкованого індексу в z N над набором z.


3

Юлія, 45 42 байти

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

Стара версія:

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

Код будує новий рядок, додаючи до нього нові символи, а потім joinз'єднує їх у потрібний рядок у кінці. Нова версія зберігає деякі символи шляхом ітерації за допомогою розуміння масиву. Також зберігається байт, використовуючи, ?:а не ||(оскільки він усуває необхідність у дужках навколо призначення).

Альтернативний розчин, 45 байт, використовуючи рекурсію і регулярний вираз:

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

Джулія, 17 байт

(Альтернативна версія)

s->join(union(s))

Це unionв основному використовує замінник unique- я не вважаю це "справжньою" відповіддю, оскільки я інтерпретую "не використовувати unique", щоб означати "не використовую єдину вбудовану функцію, що має наслідком повернення унікальної елементи ".


У мене була схожа ідея, але це було не так стисло. Хороша робота!
Олексій А.

3

Java, 78 байт

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

Простий цикл під час перевірки виводу для вже наявних символів. Приймає введення як char[].


3

C, 96 байт

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

Для цього використовується масив цілих чисел, індексований числом символів ASCII. Символи друкуються лише у тому випадку, якщо для цього місця в масиві встановлено значення FALSE. Після того, як буде знайдено кожен новий символ, місце в масиві встановлюється на TRUE. Для цього потрібен рядок тексту зі стандартного введення, що закінчується новим рядком. Він ігнорує символи, що не належать до ASCII.


Безголовки:

#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

С - 58

Дякуємо @hvd та @AShelly за те, що зберегли купу персонажів. Запропоновано кілька способів зробити його набагато коротшим, ніж оригінал:

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

Як ви бачите, зміни на місці здаються найкоротшими (поки що!) Тестова програма складається без попереджень 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
}

Дякую за всю допомогу. Я вдячний за всі поради, які можна так скоротити!


Ну, так як ваш код вже не діє C, просто прийнято поблажливими компілятори C: ви можете оголосити , rяк int(і опускаємо int) , щоб зберегти кілька байт: f(s,r)char*s;{...}. Але він обмежує ваш код платформами, де char*має той самий розмір, як intі, звичайно, там, де компілятори настільки ж поблажливі, як ваш і мій.
hvd

@hvd Це зло! Я був готовий за замовчуванням повернути значення, тому що не використовую його. Але це трохи хитріше, ніж я хотів би бути. Я думаю, що я вважаю за краще зробити це сумісним, а не йти так далеко! Дякуємо, що повернули вас до легкої сторони.
Джеррі Єремія

Ви можете зберегти один char, замінивши if(x)yнаx?y:0
ugoren

Ось функція 60 char, яка пише в stdout замість параметра масиву: f(char*s){int a[128]={0};for(;*s;s++)a[*s]++?0:putchar(*s);}
AShelly

Ви можете беззастережно копіювати *qта збільшувати лише те, qякщо персонаж з’явився раніше, що дозволяє набивати трохи більше разом: void f(char*s,char*r){for(char*q=r;*q=*s;strchr(r,*s++)<q||q++);}(Зауважте, що strchr(r,*s++)<qзавжди чітко визначено, там немає UB, тому що strchrне може повернутися NULLв цій версії.) За винятком типу повернення, він навіть коротший, ніж версія @ AShelly
hvd

2

Рубі, 30 24 символи

(Код 23 символів + параметр командного рядка з 1 символом.)

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

Проба зразка:

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

2

CJam, 9

Lq{1$-+}/

Це не перетворює рядок у набір, але виконує якусь різницю множин, щоб визначити, чи знайдений символ у рядку. Спробуйте в Інтернеті

Пояснення:

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

Ще одна версія, 13 байт:

Lq{_2$#)!*+}/

Це нічого не стосується наборів. Спробуйте в Інтернеті

Пояснення:

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 байт

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

Змінні рівняння рідко корисні, оскільки для зберігання вони займають 5 байт, але Y₁тут корисні як Xго символу рядка, економлячи 3 байти. Оскільки ми не можемо додати до порожніх рядків у TI-BASIC, ми починаємо рядок з першого символу Str1, потім перебираємо через решту рядка, додаючи всі символи, які вже не зустрічалися.

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

2

Матлаб, 46 байт

Він використовує анонімну функцію з аргументами функції як введення та виведення:

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

(Я не міг змусити це працювати в онлайн-перекладачі Octave.)

Приклад використання:

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

це також було б моєю ідеєю :) - вам не потрібно ,1з any, btw.
Йонас

@Jonas Дякую! Але хоча важко зрозуміти цей безлад дужок, 1це для triu (мені потрібно зняти діагональ), а не дляany
Луїс Мендо

2

Befunge -93, 124 байти

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

Перевірте це в цьому інтернет-перекладачі .


Це було складніше, ніж я очікував. Завтра я опублікую більш повне пояснення, якщо хтось хоче, але ось огляд того, що робить мій код.

  • До цього часу унікальні символи зберігаються в першому рядку, починаючи з 2,0 правого і простягаючись. Це перевіряється, щоб перевірити, чи є поточний символ дублікатом.
  • Кількість унікальних символів, які ви бачили дотепер, зберігається в 0,0і лічильник реєстрації дублікатів циклу зберігається в 1,0.
  • Коли видно унікальний символ, він зберігається на першому рядку, роздруковується, а лічильник 0,0збільшується.
  • Щоб уникнути проблем із читанням у наявних пробілах (ASCII 32), я поставив символ, що відповідає -1 (дійсно, 65536) у наступному слоті для наступного унікального символу.

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

Обрізання відповіді @ fschmengler за допомогою array_flipдвічі - другої версії використовує змінний метод і покладається на те, щоб передати рядок у true, відкинувши його на false, а потім повернути його до порожнього рядка в першому аргументі, щоб зберегти пару байтів у другому. Дешево!


2

Хаскелл , 29 байт

Нестійкий однорозмірний ім'я без змінної назви:

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

Той самий підрахунок, збережений у функції, названій fяк декларація верхнього рівня:

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

Зауважте, що є оптимізація, яка злегка підманює, яку я не робив у дусі приємності: технічно все-таки дозволено правилами цього виклику використовувати різні кодування вводу та виводу для рядка. Представляючи будь- stringяке його частково застосоване кодування Церкви \f -> foldr f [] string :: (a -> [b] -> [b]) -> [b](з іншого боку біекція, що надається функцією ($ (:))), це зводиться до ($ \x->(x:).filter(x/=))всього 24 символів.

Я уникав розміщення відповіді на 24 символи як свого офіційного, тому що вищевказане рішення можна було б приміряти на вищезгаданому інтерпретаторі, оскільки foldr(\x->(x:).filter(x/=))[]"Type unique chars!"тоді замість цього було б написано рішення про гольф:

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

як стенограма для буквальної декларації, яка була б найбільш божевільною:

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

Але це цілком коректна версія структури даних, представлена ​​як чисті функції. (Звичайно, ви можете також використовувати \f -> foldr f [] "Type unique chars!", але це, мабуть, нелегітимно, оскільки він використовує списки для фактичного зберігання даних, тому його складна частина повинна бути імовірно складена у функцію "відповідь", що веде до більш ніж 24 символів.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.