Типа 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
Просто для двойной проверки: означает ли правило «нет встроенных», что набор объектов запрещен?
Sp3000

@ Sp3000 Набор объектов разрешен. Только не используйте функцию или метод (если он существует), который дает вам свои уникальные элементы. И ввод / вывод должны быть строками, а не заданными объектами
Луис Мендо

@ Sp3000 Как вы думаете, было бы более интересно уменьшить число байтов вдвое, если не используются функции набора? Или лучше не менять правила после того, как задача была поставлена?
Луис Мендо

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

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

Ответы:


13

GolfScript, 2 байта

.&

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

.|

Я опубликовал это некоторое время назад в Совете по игре в гольф в теме GolfScript . Он работает путем дублирования входной строки (которая автоматически помещается в стек интерпретатором GolfScript и которая в большинстве случаев ведет себя как массив символов), а затем беря ее пересечение set ( &) или union ( |). Применение оператора set к массиву (или строке) сворачивает любые дубликаты, но сохраняет порядок элементов.


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 (но не golphed):

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

Как это работает: я вызываю Whereметод в строке с лямбда-выражением с двумя аргументами: xпредставляющий текущий элемент, iпредставляющий индекс этого элемента. IndexOfвсегда возвращает первый индекс переданного ему символа, поэтому, если iон не равен первому индексу x, это дублирующий символ и не должен быть включен.


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), удаление дубликата C.

Например, если входная строка была 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(я тоже влюбился в это сначала). Позор, потому что это был бы другой сохраненный байт.
Кос

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
  • создать "анти-гольф" язык: проверить
  • гольф это все равно: check

Это полная программа, которая вводит из 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

И сильно «закомментированная» и нелегальная версия (в Макаронах нет комментариев, поэтому я просто использую строковые литералы):

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

(Это первая настоящая макаронная программа (которая действительно что-то делает)! \ 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ключевое слово кажется также ненужным.)
manatwork

Не был уверен в правилах с функциями anon и хорошим уловом пространства.
агг

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

Пожалуйста, извините за мое незнание, но в какой момент этот фильтр уникальных значений? Похоже, он просто преобразует строку в набор в массив, а затем снова объединяет значения, в результате чего получается исходная строка.
Патрик Робертс

@PatrickRoberts это преобразование в набор. Набор по определению не имеет дубликатов
edc65

8

C # 6 - 18 + 46 = 64

using System.Linq;

а потом

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

Метод Enumerable.Unionextension указывает, что элементы возвращаются в исходном порядке:

Когда объект, возвращаемый этим методом, перечисляется, Union перечисляет первое и второе в этом порядке и возвращает каждый элемент, который еще не был получен.

Судя по другим ответам, операции набора, которые специально не предназначены для поиска уникальных значений, разрешены.


Хороший, я думал, string u(string s)=>String.Join("",s.Distinct());но это немного дольше.
Герми

@germi Спасибо. Уже был ответ, использующий Distinct()уже, но он удален, потому что Distinct()не разрешен в этой задаче, поскольку это метод, специально предназначенный для поиска уникальных значений.
HVd

Ах да ... упустил этот бит;)
germi

Является s => string.Concat(s.Union(s))действительным? Это будет делегат, переданный Func<string, string>в качестве аргумента.
Тайлер СтэндиМэн

@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')

Выполняет «установление объединения» входной строки с собой, используя метод «stable», который не сортирует, а затем печатает.

Это работает, потому что unionвозвращает только неповторяющиеся значения после слияния. Таким образом, по сути, если вы unionиспользуете строку с самим собой, она сначала создает строку, похожую на строку Type unique chars!Type unique chars!, а затем удаляет все дубликаты без сортировки.

Не нужно для unique:)


uniqueне допускается, извините! Это в определении проблемы
Луис Мендо

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

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

1
Ницца! И да, вы можете удалить, dispпотому что тогда у вас есть функция, которая возвращает строку, что разрешено
Луис Мендо

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 в свой ответ, но не в качестве основной. РЕДАКТИРОВАТЬ: Если подумать, это не сработает, потому что Befunge не имеет бесконечного пространства кода. Dangit!
El'endia Starman

@ El'endiaStarman Я думаю, что ответ на Beam также делает то же самое, поэтому, к сожалению, я не могу сказать, что был первым: 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

Python 3, 44

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

Создает выводимую строку rсимвол за символом, включая символ cиз ввода, только если мы его еще не видели.

Python 2 был бы 47, теряя 4 символа с raw_inputи сохраняя 1 на не нуждающихся в parers print.


Похоже, что сейчас консенсус заключается в том, что вы можете использовать его inputв Python 2, чтобы вы могли сделать свой байт короче.
mbomb007

4

APL, 3

∊∪/

Это применяет объединение (∪) между каждым элементом вектора, получая итерацию, которая приводит к удалению дубликатов.

Проверьте это на tryapl.org

Старый:

~⍨\

При этом используется ~ (с обратными аргументами, используя ⍨), применяемый между каждым элементом аргумента. В результате для каждого элемента, если он уже есть в списке, он стирается.


Поймать: «И ввод / вывод должны быть строками», - говорит Луис. «Unione Reduce» возвращает вложенный массив, а не строку. 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
manatwork

Вставил ли там Юникод → char, что делает его сломанным?
Стив

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

1
Нет, я вставил его со значением «изменить на».
manatwork

1
Изменение mapтакже улучшило бы экономию: map{$h{$_}||=print}<>=~/./g
manatwork

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 символы.


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

С - 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 Это зло! Я был готов вернуть значение по умолчанию, потому что я не использую его. Но это немного сложнее, чем хотелось бы. Я думаю, что я предпочел бы сделать его совместимым, а не заходить так далеко! Спасибо за возвращение на светлую сторону.
Джерри Иеремия

Вы можете сохранить один символ, заменив if(x)yнаx?y:0
ugoren

Вот функция из 60 символов, которая записывает в стандартный вывод вместо параметра массива: 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

Matlab, 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!

это тоже было бы моей идеей :) - кстати, вам не нужно с ,1with any.
Джонас

@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дважды - вторая версия использует метод переменных и полагается на приведение строки к истине, отрицание ее к ложному, затем приведение ее к пустой строке в первом аргументе, чтобы сохранить пару байтов во втором. Дешевые!


2

Haskell , 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.