Gõ uniqchars!


41

Đưa ra một chuỗi bao gồm các ký tự ASCII có thể in được , tạo ra một đầu ra bao gồm các ký tự duy nhất của nó theo thứ tự ban đầu . Nói cách khác, đầu ra giống như đầu vào ngoại trừ một char bị loại bỏ nếu nó đã xuất hiện trước đó.

Không có tích hợp nào để tìm các phần tử duy nhất trong một mảng có thể được sử dụng (ví dụ: MATLAB có uniquechức năng thực hiện điều đó). Ý tưởng là làm nó bằng tay.

Biết thêm chi tiết:

  • Hoặc chức năng hoặc các chương trình được phép.
  • Đầu vào và đầu ra có thể ở dạng đối số hàm, stdin / stdout (ngay cả đối với các hàm) hoặc kết hợp các đối số đó.
  • Nếu stdin hoặc stdout được sử dụng, một chuỗi được hiểu chỉ là chuỗi ký tự . Nếu các đối số hàm được sử dụng, chuỗi ký tự có thể cần được đặt trong dấu ngoặc kép hoặc ký hiệu tương đương mà ngôn ngữ lập trình lựa chọn sử dụng để xác định chuỗi.
  • Đầu ra phải là một chuỗi chỉ chứa các ký tự duy nhất của đầu vào. Vì vậy, không có ngắt dòng bổ sung, dấu cách, v.v. Ngoại lệ duy nhất là: nếu đầu ra được hiển thị ở thiết bị xuất chuẩn, hầu hết các chức năng hiển thị sẽ thêm một dấu \n(để tách chuỗi khỏi chuỗi tiếp theo). Vì vậy, một dấu vết \nđược chấp nhận trong thiết bị xuất chuẩn .
  • Nếu có thể, hãy đăng một liên kết đến một trình thông dịch / trình biên dịch trực tuyến để những người khác có thể thử mã của bạn.

Đây là mã golf , vì vậy mã ngắn nhất trong byte thắng.

Một số ví dụ , giả sử stdin và stdout:

  1. Chuỗi đầu vào:

    Type unique chars!
    

    Chuỗi đầu ra:

    Type uniqchars!
    
  2. Chuỗi đầu vào

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

    Chuỗi đầu ra

    "I think'sdarloe,yu
    
  3. Chuỗi đầu vào

    3.1415926535897932384626433832795
    

    Chuỗi đầu ra

    3.14592687
    

5
Chỉ cần kiểm tra lại: Liệu quy tắc không có nội dung có nghĩa là các đối tượng thiết lập không được phép?
Sp3000

@ Sp3000 Đặt đối tượng được phép. Chỉ không sử dụng một chức năng hoặc phương thức (nếu nó tồn tại) cung cấp cho bạn các yếu tố độc đáo của nó. Và đầu vào / đầu ra phải là các chuỗi, không đặt các đoạn trích
Luis Mendo

@ Sp3000 Bạn có nghĩ rằng sẽ giảm một nửa số byte thú vị hơn nếu không sử dụng chức năng thiết lập nào không? Hoặc tốt hơn không thay đổi các quy tắc một khi thách thức đã được đặt ra?
Luis Mendo

5
Tôi nghĩ hiện tại chỉ có câu trả lời của tôi sử dụng các bộ và tôi sẽ không phiền nếu bạn thay đổi nó. Tuy nhiên, tôi không thực sự chắc chắn rằng một phần thưởng như thế sẽ thay đổi nhiều, ví dụ tôi nghi ngờ rằng CJam sẽ có thể thực hiện được trong <6 byte mà không cần bộ. Ngoài ra, tôi không chắc đường kẻ nằm giữa một nội dung tìm thấy các phần tử duy nhất và xây dựng một tập hợp từ một số phần tử ...
Sp3000

1
@ Sp3000 Vâng, đó là một đường viền mờ. Tôi đã không dự đoán các chức năng thiết lập. Tôi nghĩ rằng tôi sẽ rời khỏi thử thách như bây giờ
Luis Mendo

Câu trả lời:


13

GolfScript, 2 byte

.&

Hay cách khác:

.|

Tôi đã đăng bài này cách đây một thời gian trong phần Mẹo chơi gôn trong chủ đề GolfScript . Nó hoạt động bằng cách sao chép chuỗi đầu vào (được trình thông dịch GolfScript đưa vào ngăn xếp tự động và hoạt động theo hầu hết các cách như một mảng các ký tự) và sau đó lấy chính giao điểm ( &) hoặc union ( |) của nó. Áp dụng một toán tử tập hợp cho một mảng (hoặc chuỗi) thu gọn bất kỳ bản sao nào, nhưng vẫn giữ nguyên thứ tự của các phần tử.


23

CJam, 3 byte

qL|

Setwise hoặc của đầu vào với một danh sách trống. Hoạt động thiết lập CJam bảo vệ thứ tự phần tử.

Dùng thử trực tuyến


Tôi cho rằng điều này là hợp lệ vì các bộ được cho phép, nhưng tôi không chắc ...
Sp3000

Rất thông minh! Tôi biết rằng CJam sẽ là một trong những thứ tốt nhất, nhưng tôi không mong đợi chỉ 3 byte!
Luis Mendo

19

C # 6, 18 + 67 = 85 byte

Yêu cầu usingtuyên bố này :

using System.Linq;

Phương pháp thực tế:

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

Phương pháp này lưu một số ký tự bằng cách xác định hàm là lambda , được hỗ trợ trong C # 6. Đây là giao diện của C # trước 6 (nhưng không được mã hóa):

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

Cách thức hoạt động: Tôi gọi Wherephương thức trên chuỗi bằng lambda với hai đối số: xđại diện cho phần tử hiện tại, iđại diện cho chỉ mục của phần tử đó. IndexOfluôn trả về chỉ mục đầu tiên của char được truyền cho nó, vì vậy nếu ikhông bằng chỉ mục đầu tiên của x, thì đó là một char trùng lặp và không được đưa vào.


3
Tôi thực sự không mong đợi C # sẽ ngắn như vậy. Công việc tuyệt vời!
Alex A.

Ừm. Tôi nghĩ bạn nên gửi một chương trình hoàn chỉnh (với static void Mainvv).
Timwi

3
@Timwi Thử thách này nêu rõ "Hoặc là các chức năng hoặc chương trình được cho phép."
hvd

C # cho phép tiếp cận ngắn hơn, cũng sử dụng LINQ. Tôi đã đăng một câu trả lời cạnh tranh. :)
hvd

@hvd Đẹp một cái! +1
Chương trìnhFOX

14

Võng mạc , 14 byte

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

Mỗi dòng nên đi trong tệp riêng của nó hoặc bạn có thể sử dụng -s cờ để đọc từ một tệp.

Để giải thích, chúng tôi sẽ sử dụng phiên bản dài hơn nhưng đơn giản hơn:

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

Dòng đầu tiên là regex để khớp với ( +`là chuỗi cấu hình tiếp tục chạy cho đến khi tất cả các thay thế đã được thực hiện). Regex tìm kiếm một ký tự (chúng ta sẽ gọi nó là C), theo sau là 0 hoặc nhiều ký tự tùy ý, theo sau là C. Các dấu ngoặc đơn biểu thị các nhóm bắt giữ, vì vậy chúng tôi thay thế khớp bằng C ( $1) và các ký tự ở giữa ($2 ), loại bỏ bản sao của C.

Ví dụ: nếu chuỗi đầu vào là unique, lần chạy đầu tiên sẽ khớp , tương ứng uniquvới uniqnhư $1$2. Sau đó, nó sẽ thay thế chuỗi con phù hợp trong đầu vào ban đầu bằng uniq, cho uniqe.


3
Tôi đã tìm kiếm một regex để làm điều này; Tôi không nhận ra nó quá ngắn! +1
Sản phẩm ETH

13

Perl, 21 (20 byte + -p)

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

Sử dụng:

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

1
Bạn có thể lưu 1 byte phủ định $h{$&}và sử dụng logic VÀ thay vì toán tử tạm thời:s/./!$h{$&}++&&$&/eg
kos

@kos nếu bạn hỏi tôi, tôi đã nói với bạn rằng tôi đã thử 100% điều này và kết thúc với 1s trong đầu ra, nhưng không được! Cảm ơn bạn, cập nhật!
Dom Hastings

1
Đã nâng cấp rồi :) Tôi nghĩ bạn đã thử s/./$h{$&}++||$&/eg(lúc đầu tôi cũng thích điều đó). Xấu hổ vì đó sẽ là một byte lưu khác.
kos

11

Macaroni 0.0.2 , 233 byte

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
  • tạo ngôn ngữ "chống golf": kiểm tra
  • dù sao đi nữa

Đây là một chương trình đầy đủ, đầu vào từ STDIN và đầu ra trên STDOUT.

Phiên bản bọc, cho giá trị thẩm mỹ:

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

Và một phiên bản "bình luận" và vô căn cứ (không có bình luận nào trong Macaroni, vì vậy tôi chỉ sử dụng các chuỗi ký tự trần):

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

(Đây là chương trình Macaroni thực sự đầu tiên (thực sự làm được điều gì đó)! \ O /)


5
• đặt cho ngôn ngữ một cái tên hài hước và phù hợp: kiểm tra
Luis Mendo

11

JavaScript ES7, 37 33 25 byte

Cách tiếp cận khá đơn giản bằng cách sử dụng toán tử trải rộng ES6 Setvà ES7 Array :

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

Ít hơn 22 byte so với indexOfcách tiếp cận. Làm việc trên một số ít các trường hợp thử nghiệm.


Không gian xung quanh forbiểu thức là không cần thiết và bạn có thể làm cho nó hoạt động ẩn danh như một số giải pháp khác đã làm : s=>[for(c of Set(s))c].join``. (Cập nhật nhạt: không chắc chắn 100%, nhưng newtừ khóa dường như cũng không cần thiết.)
manatwork

Không chắc chắn về các quy tắc với chức năng anon và nắm bắt tốt trên không gian.
azz

Mã được dịch mã mà không có newkết quả Uncaught TypeError: Constructor Set requires 'new'trong Google Chrome.
azz

Xin thứ lỗi cho sự thiếu hiểu biết của tôi nhưng tại thời điểm nào thì bộ lọc này có giá trị duy nhất? Có vẻ như nó chỉ chuyển đổi một chuỗi thành một tập hợp thành một mảng sau đó nối các giá trị dẫn đến chuỗi ban đầu một lần nữa.
Patrick Roberts

@PatrickRoberts đó là chuyển đổi thành một bộ. Một tập hợp theo định nghĩa không có song công
edc65

8

C # 6 - 18 + 46 = 64

using System.Linq;

và sau đó

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

Các Enumerable.Unionphương pháp quy định cụ thể mở rộng mà yếu tố được trả về theo thứ tự ban đầu:

Khi đối tượng được trả về bằng phương thức này được liệt kê, Union liệt kê thứ nhấtthứ hai theo thứ tự đó và mang lại từng phần tử chưa được mang lại.

Đặt các hoạt động không có ý định đặc biệt để tìm các giá trị duy nhất dường như được phép đánh giá bằng các câu trả lời khác.


Một điều tuyệt vời, tôi đã nghĩ đến string u(string s)=>String.Join("",s.Distinct());nhưng lâu hơn một chút.
mầm 7/10/2015

@germi Cảm ơn. Đã có câu trả lời bằng cách sử dụng Distinct(), nhưng nó đã bị xóa vì Distinct()không được phép trong thử thách này, vì đây là phương pháp dành riêng để tìm các giá trị duy nhất.
hvd

À đúng rồi ... bỏ qua bit đó;)
mầm mống 7/10/2015

s => string.Concat(s.Union(s))hợp lệ không? Đó sẽ là đại biểu được thông qua Func<string, string>như một cuộc tranh luận.
Tyler StandishMan

@TylerStandishMan Nếu điều đó hợp lệ, tôi sẽ mong đợi nhiều người sử dụng nó hơn và tôi chưa từng thấy nó trước đây, vì vậy tôi không nghĩ là như vậy. Nhưng có lẽ nó phải hợp lệ - đây có vẻ như là thứ đáng để kiểm tra trên Meta nếu bạn quan tâm.
hvd

7

JavaScript ES6, 47 byte

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

Bài kiểm tra dưới đây hoạt động trên tất cả các trình duyệt.

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>


Phần này <i?'':elàm gì?
DanTheMan

1
Đó là một nhà điều hành ternary. Nếu phiên bản đầu tiên của một ký tự enằm trước chỉ mục hiện tại i, nó sẽ trả về một chuỗi rỗng, do đó loại bỏ ký tự đó. Nếu đó là trường hợp đầu tiên, nó chỉ trả về evà không có thay đổi nào được thực hiện.
NinjaBearMonkey 7/10/2015

7

MATLAB, 23

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

Có phải "set union" của chuỗi đầu vào với chính nó, sử dụng phương thức 'ổn định' không sắp xếp và sau đó in ra.

Điều này hoạt động vì unionchỉ trả về các giá trị không trùng lặp sau khi hợp nhất. Vì vậy, về cơ bản nếu bạn unionlà chuỗi với chính nó, đầu tiên nó tạo ra một chuỗi như thế Type unique chars!Type unique chars!, và sau đó loại bỏ tất cả các bản sao mà không cần sắp xếp.

Không cần unique:)


uniquekhông được phép, xin lỗi! Đó là trong định nghĩa challange
Luis Mendo

Bỏ lỡ điều đó, đừng bận tâm.
Tom Carpenter

Theo câu trả lời của Sp3000, tôi có thể đề xuất setdiffvới 'stable'tùy chọn này không?
Luis Mendo

1
Đẹp! Và vâng, bạn có thể xóa dispvì sau đó bạn có một hàm trả về một chuỗi, được phép
Luis Mendo

1
Bạn cũng có thể sử dụng intersectvới 'stable'để đạt được hiệu quả tương tự. Tôi sẽ viết nó, nhưng đưa ra câu trả lời này, nó không còn là bản gốc lol nữa.
rayryeng - Phục hồi Monica

7

> <> , 16 byte

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

> <> không có chuỗi, vì vậy chúng tôi sử dụng codebox. Do tính chất hình xuyến của> <>, các bước sau chạy trong một vòng lặp:

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

Lưu ý rằng điều này sử dụng thực tế là đầu vào chỉ chứa ASCII có thể in được, vì điều này sẽ không hoạt động nếu có ASCII 0.


1
....... điều này thật tuyệt vời. Tôi ước tôi đã nghĩ về điều này. Tôi sẽ bao gồm một phiên bản Befunge của điều này trong câu trả lời của tôi, nhưng không phải là phiên bản chính. EDIT: Suy nghĩ thứ hai, điều này sẽ không hoạt động vì Befunge không có không gian mã vô hạn. Nguy hiểm!
El'endia Starman

@ El'endiaStarman Tôi nghĩ rằng câu trả lời Beam cũng làm điều tương tự, vì vậy thật không may, tôi không thể nói rằng mình là người đầu tiên: P
Sp3000

À, ừ, tôi nghĩ bạn đúng. Giải thích của bạn là rõ ràng hơn mặc dù.
El'endia Starman


5

Phần tử , 22 19 18 byte

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

Ví dụ đầu vào / đầu ra: hello world->helo wrd

Điều này hoạt động bằng cách đơn giản xử lý chuỗi một ký tự tại một thời điểm và theo dõi những ký tự mà nó đã thấy trước đó.

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

Trăn 3, 44

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

Xây dựng ký tự chuỗi đầu ra rtheo ký tự, bao gồm ký tự ctừ đầu vào chỉ khi chúng ta chưa thấy nó.

Python 2 sẽ là 47, mất 4 ký tự raw_inputvà tiết kiệm 1 khi không cần parers cho print.


Sự đồng thuận bây giờ dường như là bạn có thể sử dụng inputtrong Python 2, vì vậy bạn có thể làm cho bạn ngắn hơn một byte.
mbomb007

4

APL, 3

∊∪/

Điều này áp dụng liên kết (∪) giữa mỗi phần tử của vectơ, thu được một phép lặp có tác dụng loại bỏ các bản sao.

Kiểm tra nó trên tryapl.org

Người già:

~⍨\

Điều này sử dụng ~ (với các đối số đảo ngược, sử dụng ⍨) được áp dụng giữa mỗi phần tử của đối số. Kết quả là với mỗi phần tử, nếu nó đã có trong danh sách, nó sẽ bị xóa.


Luis nói: "Và đầu vào / đầu ra phải là chuỗi", Luis nói. "Unione giảm" trả về một mảng lồng nhau, không phải là một chuỗi. O :-)
lstefano

Bạn nói đúng, thêm vào đầu để sửa.
Moris Zucca

3

Perl, 54 27 byte

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

Kiểm tra:

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

1
print exists($h{$_})?"":$_$h{$_}||print
manatwork 04/10/2015

SO đã chèn một unicode → char vào đó khiến nó bị hỏng?
steve

1
sử dụng công cụ sửa đổi câu lệnh sẽ giúp bạn tiết kiệm một số byte, cùng với đề xuất của @ manatwork $h{$_}||=printvà việc sử dụng <>=~/./gsẽ giúp tiết kiệm thêm một vài chi tiết nữa!
Dom Hastings

1
Không, tôi đã chèn nó, với ý nghĩa của sự thay đổi thành tên lửa.
manatwork 04/10/2015

1
Thay đổi thành mapcũng sẽ cải thiện việc tiết kiệm: map{$h{$_}||=print}<>=~/./g
manatwork 4/10/2015

3

PHP, 72 byte 84 byte

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

Sử dụng các ký tự làm khóa cho một mảng kết hợp, sau đó in các phím. Thứ tự các phần tử mảng luôn là thứ tự chèn.

Cảm ơn Ismael Miguel cho str_splitlời đề nghị.


1
<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a));Ngắn hơn và làm như vậy.
Ismael Miguel

Tìm thấy một vòng lặp ngắn hơn : while($c=$argv[1][$i++*1]). Điều này thay thế toàn bộ foreach. Mọi thứ khác đều giống nhau
Ismael Miguel

Tôi đã thử một cái gì đó tương tự đầu tiên nhưng kiềm chế nó bởi vì nó sẽ dừng lại ở một nhân vật ép buộc thành "sai", tức là "0". Hãy thử "abc0def" làm đầu vào.
Fabian Schmengler 04/10/2015

Bạn nói đúng về nó. Surelly có một cách giải quyết cho nó mà không tốn hơn 2 byte.
Ismael Miguel

3

Bình thường, 7 byte

soxzN{z

Mã giả:

z = đầu vào

tổng chỉ số theo thứ tự tính theo z của N trên tập hợp z.


3

Julia, 45 42 byte

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

Phiên bản cũ:

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

Mã xây dựng chuỗi mới bằng cách gắn thêm các ký tự mới vào chuỗi đó, sau đó joinghép chúng lại với nhau thành một chuỗi thích hợp ở cuối. Phiên bản mới lưu một số ký tự bằng cách lặp qua việc hiểu mảng. Cũng lưu một byte bằng cách sử dụng ?:chứ không phải ||(vì nó loại bỏ sự cần thiết cho dấu ngoặc xung quanh bài tập).

Giải pháp thay thế, 45 byte, sử dụng đệ quy và regex:

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

Julia, 17 byte

(Phiên bản thay thế)

s->join(union(s))

Điều này unionvề cơ bản sử dụng thay thế cho unique- Tôi không coi đây là câu trả lời "thực", vì tôi hiểu "không sử dụng unique" có nghĩa là "không sử dụng một hàm dựng sẵn duy nhất có tác dụng trả lại duy nhất các yếu tố ".


Tôi đã có một ý tưởng tương tự nhưng nó không ngắn gọn. Công việc tốt đẹp!
Alex A.

3

Java, 78 byte

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

Một vòng lặp đơn giản trong khi kiểm tra đầu ra cho các ký tự đã có. Chấp nhận đầu vào là a char[].


3

C, 96 byte

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

Điều này sử dụng một mảng các số nguyên, được lập chỉ mục bằng số ký tự ASCII. Các ký tự chỉ được in nếu vị trí đó trong mảng được đặt thành FALSE. Sau mỗi ký tự mới được tìm thấy, vị trí trong mảng được đặt thành TRUE. Điều này có một dòng văn bản từ đầu vào tiêu chuẩn, kết thúc bởi một dòng mới. Nó bỏ qua các ký tự không phải ASCII.


Ung dung:

#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

Cảm ơn @hvd và @AShelly vì đã lưu một loạt các ký tự. Có nhiều cách được đề xuất để làm cho nó ngắn hơn nhiều so với bản gốc:

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

Như bạn có thể thấy sửa đổi tại chỗ dường như là ngắn nhất (cho đến nay!) Chương trình thử nghiệm biên dịch mà không có cảnh báo bằng cách sử dụng 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ảm ơn vì sự giúp đỡ. Tôi đánh giá cao tất cả các lời khuyên đưa ra để rút ngắn rất nhiều!


Chà, vì mã của bạn đã không hợp lệ C, chỉ cần được trình biên dịch C khoan dung chấp nhận: bạn có thể khai báo rint(và bỏ qua int) để lưu một số byte : f(s,r)char*s;{...}. Nhưng nó giới hạn mã của bạn cho các nền tảng có char*cùng kích thước intvà tất nhiên các trình biên dịch cũng khoan dung như của bạn và của tôi.
hvd

@hvd Thật là ác! Tôi sẵn sàng mặc định giá trị trả về vì tôi không sử dụng nó. Nhưng đó là một chút tinh ranh hơn tôi muốn. Tôi nghĩ rằng tôi thích làm cho nó tuân thủ hơn là đi xa! Cảm ơn đã mang trở lại phía ánh sáng.
Jerry Jeremiah

Bạn có thể lưu một char bằng cách thay thế if(x)ybằngx?y:0
ugoren 6/10/2015

Đây là một hàm 60 char ghi vào thiết bị xuất chuẩn thay vì tham số mảng: f(char*s){int a[128]={0};for(;*s;s++)a[*s]++?0:putchar(*s);}
AShelly

Bạn có thể sao chép vô điều kiện vào *qvà chỉ tăng qnếu nhân vật xuất hiện sớm hơn, cho phép nhồi thêm một chút nữa: void f(char*s,char*r){for(char*q=r;*q=*s;strchr(r,*s++)<q||q++);}(Lưu ý strchr(r,*s++)<qluôn được xác định rõ, không có UB ở đó, vì strchrkhông thể quay lại NULLtrong phiên bản này.) Ngoại trừ kiểu trả về, nó thậm chí còn ngắn hơn phiên bản của @ AShelly.
hvd

2

Ruby, 30 24 ký tự

(Mã 23 ký tự + 1 ký tự tùy chọn dòng lệnh.)

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

Chạy mẫu:

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

2

CJam, 9

Lq{1$-+}/

Điều này không chuyển đổi một chuỗi thành một tập hợp, nhưng nó thực hiện một loại khác biệt tập hợp để xác định xem một ký tự có được tìm thấy trong một chuỗi hay không. Dùng thử trực tuyến

Giải trình:

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

Một phiên bản khác, 13 byte:

Lq{_2$#)!*+}/

Điều này không làm bất cứ điều gì liên quan đến bộ. Dùng thử trực tuyến

Giải trình:

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 byte

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

Các biến phương trình hiếm khi hữu ích vì chúng mất 5 byte để lưu trữ, nhưng Y₁có ích ở đây là Xký tự thứ của chuỗi, tiết kiệm 3 byte. Vì chúng tôi không thể thêm vào chuỗi trống trong TI-BASIC, chúng tôi bắt đầu chuỗi bằng ký tự đầu tiên của Str1, sau đó lặp qua phần còn lại của chuỗi, thêm tất cả các ký tự chưa gặp phải.

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

2

Matlab, 46 byte

Nó sử dụng một hàm ẩn danh, với các đối số chức năng là đầu vào và đầu ra:

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

(Tôi không thể làm điều này để làm việc trong một thông dịch viên trực tuyến Octave.)

Ví dụ sử dụng:

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

đó cũng là ý tưởng của tôi :) - bạn không cần ,1với any, btw.
Jonas

@Jonas Cảm ơn! Mặc dù thật khó để nhìn qua mớ dấu ngoặc đơn này, cái 1dành cho triu (tôi cần xóa đường chéo), không phải choany
Luis Mendo

2

Befunge -93, 124 byte

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

Kiểm tra nó trong phiên dịch trực tuyến này .


Điều này là khó khăn hơn tôi mong đợi. Tôi sẽ đăng một lời giải thích đầy đủ hơn vào ngày mai nếu có ai muốn tôi, nhưng đây là tổng quan về những gì mã của tôi làm.

  • Các ký tự duy nhất được thấy cho đến nay được lưu trữ trên hàng đầu tiên, bắt đầu từ 2,0 và mở rộng sang bên phải. Điều này được kiểm tra để xem nếu ký tự hiện tại là một bản sao.
  • Số lượng ký tự duy nhất được nhìn thấy cho đến nay được lưu trữ trong 0,0và bộ đếm vòng lặp kiểm tra trùng lặp được lưu trữ trong 1,0.
  • Khi nhìn thấy một ký tự duy nhất, nó được lưu trữ ở hàng đầu tiên, được in ra và bộ đếm trong 0,0 được tăng lên.
  • Để tránh các vấn đề với việc đọc trong khoảng trắng hiện tại (ASCII 32), tôi đặt ký tự tương ứng với -1 (thực sự, 65536) vào vị trí tiếp theo cho ký tự duy nhất tiếp theo.

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

Chỉnh sửa câu trả lời của @ fschmengler bằng cách sử dụng array_fliphai lần - phiên bản thứ hai sử dụng phương thức biến và dựa vào việc truyền chuỗi thành đúng, phủ định nó thành sai, sau đó chuyển nó trở lại chuỗi trống trong đối số thứ nhất để lưu một vài byte trong giây. Rẻ!


2

Haskell , 29 byte

Nestable, không có tên biến một-liner:

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

Cùng một số đếm, được lưu vào một hàm có tên flà khai báo cấp cao nhất:

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

Lưu ý rằng có một tối ưu hóa hơi gian lận mà tôi chưa thực hiện theo tinh thần độc đáo: về mặt kỹ thuật vẫn được phép theo quy tắc của thách thức này để sử dụng mã hóa đầu vào và đầu ra khác nhau cho một chuỗi. Bằng cách thể hiện bất kỳ stringbằng mã hóa Church được áp dụng một phần của nó \f -> foldr f [] string :: (a -> [b] -> [b]) -> [b](với phía bên kia của mệnh đề được cung cấp bởi hàm ($ (:))), điều này sẽ được đánh xuống ($ \x->(x:).filter(x/=)), chỉ có 24 ký tự.

Tôi đã tránh đăng phản hồi 24 ký tự làm chính thức của mình vì giải pháp trên có thể được thử trên trình thông dịch ở trên vì foldr(\x->(x:).filter(x/=))[]"Type unique chars!"trong khi đó giải pháp đánh gôn sẽ được viết thay thế:

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

như một cách viết tắt cho tuyên bố theo nghĩa đen sẽ là điên rồ hơn:

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

Nhưng đó là một phiên bản hoàn toàn hợp lệ của cấu trúc dữ liệu được biểu diễn dưới dạng các hàm thuần túy. (Tất nhiên, bạn có thể sử dụng \f -> foldr f [] "Type unique chars!"quá, nhưng đó là lẽ bất hợp pháp vì nó sử dụng danh sách này để thực sự lưu trữ dữ liệu, vì vậy phần foldr của nó nên sau đó có lẽ được sáng tác vào chức năng "câu trả lời", dẫn đến hơn 24 ký tự.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.