Xây dựng biểu đồ ASCII gồm các từ được sử dụng phổ biến nhất trong một văn bản đã cho [đóng]


156

Các thách thức:

Xây dựng biểu đồ ASCII của các từ được sử dụng phổ biến nhất trong một văn bản nhất định.

Những quy định:

  • Chỉ chấp nhận a-zA-Z(ký tự chữ cái) là một phần của một từ.
  • Bỏ qua vỏ ( She== shecho mục đích của chúng tôi).
  • Bỏ qua những từ sau (khá đơn giản, tôi biết): the, and, of, to, a, i, it, in, or, is
  • Làm rõ: xem xét don't: điều này sẽ được coi là 2 'từ' khác nhau trong phạm vi a-zA-Z: ( dont).

  • Tùy chọn (bây giờ đã quá muộn để thay đổi chính thức các thông số kỹ thuật), bạn có thể chọn bỏ tất cả các chữ cái 'từ' (điều này có khả năng cũng có thể rút ngắn danh sách bỏ qua).

Phân tích cú pháp đã cho text(đọc một tệp được chỉ định thông qua các đối số dòng lệnh hoặc được đặt trong; giả định us-ascii) và xây dựng cho chúng ta một word frequency chartđặc điểm sau:

  • Hiển thị biểu đồ (cũng xem ví dụ bên dưới) cho 22 từ phổ biến nhất (được sắp xếp theo tần số giảm dần).
  • Thanh widthđại diện cho số lần xuất hiện (tần số) của từ (tỷ lệ). Nối một khoảng trắng và in từ.
  • Đảm bảo các thanh này (cộng với dấu cách-không gian-từ) luôn luôn vừa vặn : bar+ [space]+ word+ [space]phải luôn luôn <= 80ký tự (đảm bảo bạn tính đến độ dài thanh và từ khác nhau có thể có: vd: từ phổ biến thứ hai có thể dài hơn rất nhiều sau đó đầu tiên trong khi không khác nhau rất nhiều về tần số). Tối đa hóa chiều rộng thanh trong các ràng buộc này và chia tỷ lệ các thanh một cách thích hợp (theo tần số mà chúng đại diện).

Một ví dụ:

Văn bản cho ví dụ có thể được tìm thấy ở đây ( Cuộc phiêu lưu của Alice ở xứ sở thần tiên, của Lewis Carroll ).

Văn bản cụ thể này sẽ mang lại biểu đồ sau:

 Giới thiệu
| _________________________________________________________________________ | bà ấy
| _____________________________________________________________ | bạn
| ____________________________________________________________ | nói
| ____________________________________________________ | alice
| ____________________________________________ | là
| cái đó
| như
| cô ấy
| với
| tại
| S
| t
| trên
| tất cả
| điều này
| cho
| đã có
| nhưng
| là
| không phải
| họ
| vì thế


Để biết thông tin của bạn: đây là các tần số mà biểu đồ trên được xây dựng dựa trên:

[('Cô', 553), ('bạn', 481), ('đã nói', 462), ('alice', 403), ('là', 358), ('đó
', 330), (' như ', 274), (' cô ấy ', 248), (' với ', 227), (' tại ', 227), (' s ', 219), (' t '
, 218), ('trên', 204), ('tất cả', 200), ('này', 181), ('cho', 179), ('đã', 178), ('
nhưng ', 175), (' được ', 167), (' không ', 166), (' họ ', 155), (' vì vậy ', 152)]

Một ví dụ thứ hai (để kiểm tra xem bạn đã triển khai thông số kỹ thuật hoàn chỉnh chưa): Thay thế mọi lần xuất hiện trong tệp Alice in Wonderlandyou được liên kết bằng :superlongstringstring

 Giới thiệu
| ______________________________________________________________ | bà ấy
| _____________________________________________________ | siêu dây
| ___________________________________________________ | nói
| ____________________________________________ | alice
| ______________________________________ | là
| cái đó
| như
| cô ấy
| với
| tại
| _______________ | S
| _______________ | t
| trên
| tất cả
| điều này
| cho
| đã có
| nhưng
| là
| không phải
| ______________ | họ
| ______________ | vì thế

Người chiến thắng:

Giải pháp ngắn nhất (theo số lượng ký tự, mỗi ngôn ngữ). Chúc vui vẻ!


Chỉnh sửa : Bảng tóm tắt kết quả cho đến nay (2012 / 02-15) (ban đầu được thêm bởi người dùng Nas Banov):

Ngôn ngữ thư giãn nghiêm ngặt
========= ======= ======
GolfScript 130 143
Perl 185
Windows PowerShell 148 199
Toán học 199
Hồng ngọc 185 205
Unix Toolchain 194 228
Con trăn 183 243
Clojure 282
Scala 311
Haskell 333
Awk 336
R 298
Javascript 304 354
Groovy 321
Matlab 404
C # 422
Smalltalk 386
PHP 450
F # 452
TSQL 483 507

Các con số biểu thị độ dài của giải pháp ngắn nhất trong một ngôn ngữ cụ thể. "Nghiêm" đề cập đến một giải pháp thực hiện hoàn toàn thông số kỹ thuật (vẽ |____|các thanh, đóng thanh đầu tiên trên đầu bằng một ____dòng, tính đến khả năng các từ dài có tần số cao, v.v.). "Thư giãn" có nghĩa là một số quyền tự do đã được thực hiện để rút ngắn giải pháp.

Chỉ có các giải pháp ngắn hơn 500 ký tự được bao gồm. Danh sách các ngôn ngữ được sắp xếp theo độ dài của giải pháp 'nghiêm ngặt'. 'Unix Toolchain' được sử dụng để biểu thị các giải pháp khác nhau sử dụng shell * nix truyền thống cộng với hỗn hợp các công cụ (như grep, tr, sort, uniq, head, perl, awk).


4
Chà, 'thanh dài nhất' + word = 80 có thể không vừa trong 80 cols nếu từ phổ biến thứ hai là từ dài hơn nhiều. Tôi đang tìm kiếm "hạn chế tối đa" tôi đoán.
Brian

1
Chúng ta có bình thường hóa vỏ? 'Cô ấy' = 'cô ấy'?
Brian

2
IMO thực hiện việc này, cả về thời gian thực hiện và sử dụng bộ nhớ, có vẻ như là một thử thách thú vị hơn so với số lượng nhân vật.
Nông dân Frank

81
Tôi rất vui khi thấy những từ yêu thích của tôi stđược đại diện.
indiv

8
@indiv, @Nas Banov - mã thông báo quá đơn giản ngớ ngẩn đọc "did" là {didn, t} và "she" là {she, s} :)
hobbs

Câu trả lời:


123

LabVIEW 51 nút, 5 cấu trúc, 10 sơ đồ

Dạy voi nhảy tap không bao giờ đẹp. Tôi sẽ, ah, bỏ qua số lượng nhân vật.

labVIEW code

results

Chương trình chảy từ trái sang phải:

labVIEW code explained


10
Nó không đáng

4
LabVIEW rất hài lòng trong lĩnh vực kiểm soát và đo lường phần cứng, nhưng thực sự khá khủng khiếp cho thao tác chuỗi.
Joe Z

19
Câu trả lời golf mã tốt nhất mà tôi đã thấy. +1 để suy nghĩ bên ngoài hộp!
Blair Holloway

1
Hãy đếm các yếu tố cho chúng tôi ... mỗi hộp và tiện ích bạn phải kéo vào màn hình đếm.
dmckee --- ex-moderator mèo con

1
Có thể thêm một liên kết đến một phiên bản lớn hơn của các biểu đồ đó không?
Svish

42

Ruby 1.9, 185 ký tự

(chủ yếu dựa trên các giải pháp Ruby khác)

w=($<.read.downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).group_by{|x|x}.map{|x,y|[-y.size,x]}.sort[0,22]
k,l=w[0]
puts [?\s+?_*m=76-l.size,w.map{|f,x|?|+?_*(f*m/k)+"| "+x}]

Thay vì sử dụng bất kỳ chuyển đổi dòng lệnh như các giải pháp khác, bạn chỉ cần chuyển tên tệp làm đối số. (tức là ruby1.9 wordfrequency.rb Alice.txt)

Vì tôi đang sử dụng ký tự chữ ở đây, giải pháp này chỉ hoạt động trong Ruby 1.9.

Chỉnh sửa: Dấu chấm phẩy thay thế bằng dấu ngắt dòng cho "khả năng đọc". : P

Chỉnh sửa 2: Shtééf chỉ ra rằng tôi đã quên không gian dấu - đã sửa nó.

Chỉnh sửa 3: Xóa lại dấu cách;)


Nó thiếu không gian dấu, sau mỗi từ.
Stéphan Kochen

Aww bắn, coi thường mà. Có vẻ như sân golf vừa được cập nhật, không gian cần thiết không còn nữa. :)
Stéphan Kochen

Có vẻ như không phù hợp với 'chuỗi siêu dài' ở vị trí thứ 2 trở lên? (xem mô tả vấn đề)
Nas Banov

2
Điều đó có vẻ thực sự duy trì.
Zombie

39

GolfScript, 177 175 173 167 164 163 144 131 130 chars

Chậm - 3 phút cho văn bản mẫu (130)

{32|.123%97<n@if}%]''*n%"oftoitinorisa"2/-"theandi"3/-$(1@{.3$>1{;)}if}/]2/{~~\;}$22<.0=~:2;,76\-:1'_':0*' '\@{"
|"\~1*2/0*'| '@}/

Giải trình:

{           #loop through all characters
 32|.       #convert to uppercase and duplicate
 123%97<    #determine if is a letter
 n@if       #return either the letter or a newline
}%          #return an array (of ints)
]''*        #convert array to a string with magic
n%          #split on newline, removing blanks (stack is an array of words now)
"oftoitinorisa"   #push this string
2/          #split into groups of two, i.e. ["of" "to" "it" "in" "or" "is" "a"]
-           #remove any occurrences from the text
"theandi"3/-#remove "the", "and", and "i"
$           #sort the array of words
(1@         #takes the first word in the array, pushes a 1, reorders stack
            #the 1 is the current number of occurrences of the first word
{           #loop through the array
 .3$>1{;)}if#increment the count or push the next word and a 1
}/
]2/         #gather stack into an array and split into groups of 2
{~~\;}$     #sort by the latter element - the count of occurrences of each word
22<         #take the first 22 elements
.0=~:2;     #store the highest count
,76\-:1     #store the length of the first line
'_':0*' '\@ #make the first line
{           #loop through each word
"
|"\~        #start drawing the bar
1*2/0       #divide by zero
*'| '@      #finish drawing the bar
}/

"Chính xác" (hy vọng). (143)

{32|.123%97<n@if}%]''*n%"oftoitinorisa"2/-"theandi"3/-$(1@{.3$>1{;)}if}/]2/{~~\;}$22<..0=1=:^;{~76@,-^*\/}%$0=:1'_':0*' '\@{"
|"\~1*^/0*'| '@}/

Ít chậm hơn - nửa phút. (162)

'"'/' ':S*n/S*'"#{%q
'\+"
.downcase.tr('^a-z','
')}\""+~n%"oftoitinorisa"2/-"theandi"3/-$(1@{.3$>1{;)}if}/]2/{~~\;}$22<.0=~:2;,76\-:1'_':0*S\@{"
|"\~1*2/0*'| '@}/

Đầu ra có thể nhìn thấy trong nhật ký sửa đổi.


2
Giới thiệu về GolfScript: golfscript.com/golfscript
Assaf Lavie

2
Không chính xác, trong đó nếu từ thứ hai thực sự dài, nó sẽ gói sang dòng tiếp theo.
Gabe

5
"chia cho số không" ... GolfScript cho phép điều đó?
JAB

35

206

shell, grep, tr, grep, sort, uniq, sort, head, perl

~ % wc -c wfg
209 wfg
~ % cat wfg
egrep -oi \\b[a-z]+|tr A-Z a-z|egrep -wv 'the|and|of|to|a|i|it|in|or|is'|sort|uniq -c|sort -nr|head -22|perl -lape'($f,$w)=@F;$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'
~ % # usage:
~ % sh wfg < 11.txt

hm, chỉ thấy ở trên: sort -nr-> sort -nvà sau đó head-> tail=> 208 :)
update2: erm, tất nhiên những điều trên là ngớ ngẩn, vì nó sẽ bị đảo ngược sau đó. Vì vậy, 209.
update3: tối ưu hóa regrec loại trừ -> 206

egrep -oi \\b[a-z]+|tr A-Z a-z|egrep -wv 'the|and|o[fr]|to|a|i[tns]?'|sort|uniq -c|sort -nr|head -22|perl -lape'($f,$w)=@F;$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'



để giải trí, đây là phiên bản chỉ có perl (nhanh hơn nhiều):

~ % wc -c pgolf
204 pgolf
~ % cat pgolf
perl -lne'$1=~/^(the|and|o[fr]|to|.|i[tns])$/i||$f{lc$1}++while/\b([a-z]+)/gi}{@w=(sort{$f{$b}<=>$f{$a}}keys%f)[0..21];$Q=$f{$_=$w[0]};$B=76-y///c;print" "."_"x$B;print"|"."_"x($B*$f{$_}/$Q)."| $_"for@w'
~ % # usage:
~ % sh pgolf < 11.txt

35

Giải pháp dựa trên bộ SQL giao dịch (SQL Server 2005) 1063 892 873 853 827 820 783 683 647 644 630 ký tự

Cảm ơn Gabe về một số gợi ý hữu ích để giảm số lượng nhân vật.

NB: Ngắt dòng được thêm vào để tránh thanh cuộn chỉ yêu cầu ngắt dòng cuối cùng.

DECLARE @ VARCHAR(MAX),@F REAL SELECT @=BulkColumn FROM OPENROWSET(BULK'A',
SINGLE_BLOB)x;WITH N AS(SELECT 1 i,LEFT(@,1)L UNION ALL SELECT i+1,SUBSTRING
(@,i+1,1)FROM N WHERE i<LEN(@))SELECT i,L,i-RANK()OVER(ORDER BY i)R INTO #D
FROM N WHERE L LIKE'[A-Z]'OPTION(MAXRECURSION 0)SELECT TOP 22 W,-COUNT(*)C
INTO # FROM(SELECT DISTINCT R,(SELECT''+L FROM #D WHERE R=b.R FOR XML PATH
(''))W FROM #D b)t WHERE LEN(W)>1 AND W NOT IN('the','and','of','to','it',
'in','or','is')GROUP BY W ORDER BY C SELECT @F=MIN(($76-LEN(W))/-C),@=' '+
REPLICATE('_',-MIN(C)*@F)+' 'FROM # SELECT @=@+' 
|'+REPLICATE('_',-C*@F)+'| '+W FROM # ORDER BY C PRINT @

Phiên bản dễ đọc

DECLARE @  VARCHAR(MAX),
        @F REAL
SELECT @=BulkColumn
FROM   OPENROWSET(BULK'A',SINGLE_BLOB)x; /*  Loads text file from path
                                             C:\WINDOWS\system32\A  */

/*Recursive common table expression to
generate a table of numbers from 1 to string length
(and associated characters)*/
WITH N AS
     (SELECT 1 i,
             LEFT(@,1)L

     UNION ALL

     SELECT i+1,
            SUBSTRING(@,i+1,1)
     FROM   N
     WHERE  i<LEN(@)
     )
  SELECT   i,
           L,
           i-RANK()OVER(ORDER BY i)R
           /*Will group characters
           from the same word together*/
  INTO     #D
  FROM     N
  WHERE    L LIKE'[A-Z]'OPTION(MAXRECURSION 0)
             /*Assuming case insensitive accent sensitive collation*/

SELECT   TOP 22 W,
         -COUNT(*)C
INTO     #
FROM     (SELECT DISTINCT R,
                          (SELECT ''+L
                          FROM    #D
                          WHERE   R=b.R FOR XML PATH('')
                          )W
                          /*Reconstitute the word from the characters*/
         FROM             #D b
         )
         T
WHERE    LEN(W)>1
AND      W NOT IN('the',
                  'and',
                  'of' ,
                  'to' ,
                  'it' ,
                  'in' ,
                  'or' ,
                  'is')
GROUP BY W
ORDER BY C

/*Just noticed this looks risky as it relies on the order of evaluation of the 
 variables. I'm not sure that's guaranteed but it works on my machine :-) */
SELECT @F=MIN(($76-LEN(W))/-C),
       @ =' '      +REPLICATE('_',-MIN(C)*@F)+' '
FROM   #

SELECT @=@+' 
|'+REPLICATE('_',-C*@F)+'| '+W
             FROM     #
             ORDER BY C

PRINT @

Đầu ra

 _________________________________________________________________________ 
|_________________________________________________________________________| she
|_______________________________________________________________| You
|____________________________________________________________| said
|_____________________________________________________| Alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| at
|_____________________________| with
|__________________________| on
|__________________________| all
|_______________________| This
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| So
|___________________| very
|__________________| what

Và với chuỗi dài

 _______________________________________________________________ 
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|____________________________________________________| said
|______________________________________________| Alice
|________________________________________| was
|_____________________________________| that
|_______________________________| as
|____________________________| her
|_________________________| at
|_________________________| with
|_______________________| on
|______________________| all
|____________________| This
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|__________________| not
|_________________| they
|_________________| So
|________________| very
|________________| what

12
Tôi đã cho bạn +1 vì bạn đã làm điều đó trong T-SQL và để trích dẫn Team America - "Bạn có bóng. Tôi thích bóng."

Tôi đã tự do chuyển đổi một số không gian thành dòng mới để làm cho nó dễ đọc hơn. Hy vọng tôi đã không làm mọi thứ rối tung lên. Tôi cũng rút gọn nó thêm một chút.
Gabe

3
Mã đó đang hét vào mặt tôi! : O
Joey

1
Một cách tốt để tiết kiệm là thay đổi 0.000thành chỉ 0, sau đó sử dụng -Cthay vì 1.0/C. Và làm FLOATvào REALsẽ tiết kiệm một đột quỵ quá. Tuy nhiên, điều lớn nhất là có vẻ như bạn có rất nhiều AStrường hợp nên là tùy chọn.
Gabe

1
OK, thế còn SELECT [ ] FROM (SELECT $0 O, ' '+REPLICATE('_', MAX(C)*@F)+' ' [ ] FROM # UNION SELECT $1/C, '|'+REPLICATE('_',C*@F)+'| '+W FROM #)X ORDER BY O?
Gabe

34

Ruby 207 213 211 210 207 203 201 200 ký tự

Một cải tiến trên Anurag, kết hợp đề xuất từ ​​rfusca. Cũng loại bỏ đối số để sắp xếp và một vài môn đánh gôn nhỏ khác.

w=(STDIN.read.downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).group_by{|x|x}.map{|x,y|[-y.size,x]}.sort.take 22;k,l=w[0];m=76.0-l.size;puts' '+'_'*m;w.map{|f,x|puts"|#{'_'*(m*f/k)}| #{x} "}

Thực thi như:

ruby GolfedWordFrequencies.rb < Alice.txt

Chỉnh sửa: đặt 'đặt' trở lại, cần phải ở đó để tránh có dấu ngoặc kép ở đầu ra.
Edit2: Tập tin đã thay đổi-> IO
Edit3: remove / i
Edit4: Đã xóa dấu ngoặc đơn xung quanh (f * 1.0), kể lại
Edit5: Sử dụng chuỗi bổ sung cho dòng đầu tiên; mở rộng stại chỗ.
Chỉnh sửa6: Thực hiện m float, xóa 1.0. EDIT: Không hoạt động, thay đổi độ dài. EDIT: Không tệ hơn trước
Edit7: Sử dụng STDIN.read.


+1 - thích phần sắp xếp, rất thông minh :)
Anurag

Này, tối ưu hóa nhỏ so với sắp tới với phần lớn của nó ở nơi đầu tiên. :)
Archgoon

Đẹp! Đã thêm hai trong số những thay đổi tôi cũng đã thực hiện trong phiên bản của Anurag. Tắt hết 4.
Stéphan Kochen

Giải pháp đã đi chệch khỏi đầu ra ban đầu, tôi sẽ tập trung và tìm hiểu xem điều đó đã xảy ra ở đâu.
Archgoon

1
Có một biến thể ngắn hơn về điều này xuống hơn nữa.
Archgoon

28

Mathicala ( 297 284 248 244 242 199 chars) Chức năng thuần túy

và Kiểm tra Luật của Zipf

Nhìn Mamma ... không vars, không tay, .. không đầu

Chỉnh sửa 1> một số tốc ký được xác định (284 ký tự)

f[x_, y_] := Flatten[Take[x, All, y]]; 

BarChart[f[{##}, -1], 
         BarOrigin -> Left, 
         ChartLabels -> Placed[f[{##}, 1], After], 
         Axes -> None
] 
& @@
Take[
  SortBy[
     Tally[
       Select[
        StringSplit[ToLowerCase[Import[i]], RegularExpression["\\W+"]], 
       !MemberQ[{"the", "and", "of", "to", "a", "i", "it", "in", "or","is"}, #]&]
     ], 
  Last], 
-22]

Một số giải thích

Import[] 
   # Get The File

ToLowerCase []
   # To Lower Case :)

StringSplit[ STRING , RegularExpression["\\W+"]]
   # Split By Words, getting a LIST

Select[ LIST, !MemberQ[{LIST_TO_AVOID}, #]&]
   #  Select from LIST except those words in LIST_TO_AVOID
   #  Note that !MemberQ[{LIST_TO_AVOID}, #]& is a FUNCTION for the test

Tally[LIST]
   # Get the LIST {word,word,..} 
     and produce another  {{word,counter},{word,counter}...}

SortBy[ LIST ,Last]
   # Get the list produced bt tally and sort by counters
     Note that counters are the LAST element of {word,counter}

Take[ LIST ,-22]
   # Once sorted, get the biggest 22 counters

BarChart[f[{##}, -1], ChartLabels -> Placed[f[{##}, 1], After]] &@@ LIST
   # Get the list produced by Take as input and produce a bar chart

f[x_, y_] := Flatten[Take[x, All, y]]
   # Auxiliary to get the list of the first or second element of lists of lists x_
     dependending upon y
   # So f[{##}, -1] is the list of counters
   # and f[{##}, 1] is the list of words (labels for the chart)

Đầu ra

văn bản thay thế http://i49.tinypic.com/2n8mrer.jpg

Mathematica không phù hợp để chơi gôn và đó chỉ là do các tên hàm mô tả dài. Các chức năng như "Chính quy []" hoặc "StringSplit []" chỉ khiến tôi nức nở :(.

Kiểm tra luật của Zipf

Định luật của Zipf dự đoán rằng đối với một văn bản ngôn ngữ tự nhiên, Lô (Nhật ký ) so với Nhật ký (lần xuất hiện) theo một mối quan hệ tuyến tính .

Luật này được sử dụng trong việc phát triển các thuật toán để ghi mã và nén dữ liệu. (Nhưng nó KHÔNG phải là "Z" trong thuật toán LZW).

Trong văn bản của chúng tôi, chúng tôi có thể kiểm tra nó với những điều sau đây

 f[x_, y_] := Flatten[Take[x, All, y]]; 
 ListLogLogPlot[
     Reverse[f[{##}, -1]], 
     AxesLabel -> {"Log (Rank)", "Log Counter"}, 
     PlotLabel -> "Testing Zipf's Law"]
 & @@
 Take[
  SortBy[
    Tally[
       StringSplit[ToLowerCase[b], RegularExpression["\\W+"]]
    ], 
   Last],
 -1000]

Kết quả là (khá tốt tuyến tính)

văn bản thay thế http://i46.tinypic.com/33fcmdk.jpg

Chỉnh sửa 6> (242 Chars)

Tái cấu trúc Regex (không còn chức năng Chọn nữa)
Thả 1 char char
Định nghĩa hiệu quả hơn cho hàm "f"

f = Flatten[Take[#1, All, #2]]&; 
BarChart[
     f[{##}, -1], 
     BarOrigin -> Left, 
     ChartLabels -> Placed[f[{##}, 1], After], 
     Axes -> None] 
& @@
  Take[
    SortBy[
       Tally[
         StringSplit[ToLowerCase[Import[i]], 
          RegularExpression["(\\W|\\b(.|the|and|of|to|i[tns]|or)\\b)+"]]
       ],
    Last],
  -22]

Chỉnh sửa 7 → 199 ký tự

BarChart[#2, BarOrigin->Left, ChartLabels->Placed[#1, After], Axes->None]&@@ 
  Transpose@Take[SortBy[Tally@StringSplit[ToLowerCase@Import@i, 
    RegularExpression@"(\\W|\\b(.|the|and|of|to|i[tns]|or)\\b)+"],Last], -22]
  • Thay thế fbằng TransposeSlot( #1/ #2) đối số.
  • Chúng tôi không cần dấu ngoặc của stinkin (sử dụng f@xthay vì f[x]nếu có thể)


9
Bạn nghĩ rằng "Chính quy" là xấu? Tôi đã khóc khi tôi gõ "System.Text.RegularExpressions.Regex.Split" vào phiên bản C #, cho đến khi tôi thấy mã Objective-C: "stringWithContentsOfFile", "enum CảSubstringsInRange", "NSStringEnum" .
Gabe

2
@Gabe Cảm ơn ... Tôi cảm thấy tốt hơn bây giờ. Trong tiếng Tây Ban Nha, chúng tôi nói "mal de muchos, consuelo de tontos" .. Một cái gì đó như "Nhiều người gặp rắc rối, những kẻ ngốc nhẹ nhõm": D
Tiến sĩ belisarius

1
Điều |i|này là dư thừa trong regex của bạn bởi vì bạn đã có .|.
Gabe

1
Tôi thích câu nói đó của Tây Ban Nha. Điều gần nhất tôi có thể nghĩ bằng tiếng Anh là "misery love company". Đây là nỗ lực dịch thuật của tôi: "Đó là một kẻ ngốc, khi đau khổ, có được sự an ủi khi nghĩ về người khác trong tình huống tương tự." Công việc tuyệt vời về việc thực hiện Mathicala, btw.
dreeves

@dreeves Sự ngu ngốc dễ dàng vượt qua rào cản ngôn ngữ ... Rất vui khi thấy bạn thích chương trình
Mathicala

26

C # - 510 451 436 446 434 426 422 ký tự (rút gọn)

Không phải là ngắn, nhưng bây giờ có lẽ đúng! Lưu ý, phiên bản trước không hiển thị dòng đầu tiên của các thanh, không chia tỷ lệ các thanh chính xác, tải xuống tệp thay vì lấy từ stdin và không bao gồm tất cả các chi tiết C # cần thiết. Bạn có thể dễ dàng cạo nhiều nét nếu C # không cần quá nhiều tào lao. Có lẽ Powershell có thể làm tốt hơn.

using C=System.Console;   // alias for Console
using System.Linq;  // for Split, GroupBy, Select, OrderBy, etc.

class Class // must define a class
{
    static void Main()  // must define a Main
    {
        // split into words
        var allwords = System.Text.RegularExpressions.Regex.Split(
                // convert stdin to lowercase
                C.In.ReadToEnd().ToLower(),
                // eliminate stopwords and non-letters
                @"(?:\b(?:the|and|of|to|a|i[tns]?|or)\b|\W)+")
            .GroupBy(x => x)    // group by words
            .OrderBy(x => -x.Count()) // sort descending by count
            .Take(22);   // take first 22 words

        // compute length of longest bar + word
        var lendivisor = allwords.Max(y => y.Count() / (76.0 - y.Key.Length));

        // prepare text to print
        var toPrint = allwords.Select(x=> 
            new { 
                // remember bar pseudographics (will be used in two places)
                Bar = new string('_',(int)(x.Count()/lendivisor)), 
                Word=x.Key 
            })
            .ToList();  // convert to list so we can index into it

        // print top of first bar
        C.WriteLine(" " + toPrint[0].Bar);
        toPrint.ForEach(x =>  // for each word, print its bar and the word
            C.WriteLine("|" + x.Bar + "| " + x.Word));
    }
}

422 ký tự có lendivisor được nội tuyến (làm cho nó chậm hơn 22 lần) ở dạng bên dưới (dòng mới được sử dụng cho các không gian được chọn):

using System.Linq;using C=System.Console;class M{static void Main(){var
a=System.Text.RegularExpressions.Regex.Split(C.In.ReadToEnd().ToLower(),@"(?:\b(?:the|and|of|to|a|i[tns]?|or)\b|\W)+").GroupBy(x=>x).OrderBy(x=>-x.Count()).Take(22);var
b=a.Select(x=>new{p=new string('_',(int)(x.Count()/a.Max(y=>y.Count()/(76d-y.Key.Length)))),t=x.Key}).ToList();C.WriteLine(" "+b[0].p);b.ForEach(x=>C.WriteLine("|"+x.p+"| "+x.t));}}

+1 cho ass thông minh tải tập tin nội tuyến. :)
sarnold

1
Ăn cắp URL ngắn từ câu trả lời của Matt.
indiv

2
Thông số kỹ thuật cho biết tệp phải được dẫn vào hoặc chuyển qua dưới dạng đối số. Nếu bạn cho rằng args [0] chứa tên tệp cục bộ, bạn có thể rút ngắn đáng kể bằng cách sử dụng args [0] thay vì (WebClient mới ()). DownloadString (@ " gutenberg.org/files/11/11. txt " ) -> nó sẽ giúp bạn tiết kiệm khoảng 70 ký tự
thorkia

1
Đây là phiên bản thay thế cuộc gọi WebClient bằng args 0, cuộc gọi đến StreamReader và xóa một vài khoảng trắng thừa. Tổng số char = 413 var a = Regex.Replace ((new StreamReader (args [0])). ReadToEnd (), "[^ a-zA-Z]", "") .ToLower (). Split ('' ) .Where (x =>! (Mới [] {"the", "và", "của", "đến", "a", "i", "nó", "trong", "hoặc", " là "}). Chứa (x)). GroupBy (x => x) .Select (g => new {w = g.Key, c = g.Count ()}). OrderByDesceinating (x => xc). Bỏ qua (1) .Take (22) .ToList (); var m = a.OrderByDesceinating (x => xc) .Đầu tiên (); a.ForEach (x => Console.WriteLine ("|" + Chuỗi mới (' _ ', xc * (80-mwLpm-4) / mc) + "|" + xw));
thorkia

"StreamReader mới" mà không "sử dụng" là bẩn. File.ReadAllText (args [0]) hoặc Console.In.ReadToEnd () tốt hơn nhiều. Trong trường hợp sau, bạn thậm chí có thể xóa đối số khỏi Main (). :)
Rotsor

25

Perl, 237 229 209 ký tự

(Được cập nhật một lần nữa để đánh bại phiên bản Ruby với nhiều thủ thuật chơi bẩn hơn, thay thế split/[^a-z/,lcbằnglc=~/[a-z]+/g , và loại bỏ một tấm séc trị chuỗi rỗng ở nơi khác. Chúng được lấy cảm hứng từ phiên bản Ruby, vì vậy tín dụng mà tín dụng là do.)

Cập nhật: ngay bây giờ với Perl 5.10! Thay thế printbằng say, và sử dụng ~~để tránh a map. Điều này phải được gọi trên dòng lệnh như perl -E '<one-liner>' alice.txt. Vì toàn bộ tập lệnh nằm trên một dòng, nên viết nó dưới dạng một dòng không nên gặp bất kỳ khó khăn nào :).

 @s=qw/the and of to a i it in or is/;$c{$_}++foreach grep{!($_~~@s)}map{lc=~/[a-z]+/g}<>;@s=sort{$c{$b}<=>$c{$a}}keys%c;$f=76-length$s[0];say" "."_"x$f;say"|"."_"x($c{$_}/$c{$s[0]}*$f)."| $_ "foreach@s[0..21];

Lưu ý rằng phiên bản này bình thường hóa cho trường hợp. Điều này không rút ngắn bất kỳ giải pháp nào, vì việc gỡ bỏ ,lc(đối với vỏ thấp hơn) yêu cầu bạn thêm A-Zvào biểu thức phân tách, vì vậy đó là một lần rửa.

Nếu bạn đang ở trên một hệ thống có dòng mới là một ký tự chứ không phải hai ký tự, bạn có thể rút ngắn ký tự này bằng hai ký tự khác bằng cách sử dụng dòng mới theo nghĩa đen \n. Tuy nhiên, tôi đã không viết mẫu trên theo cách đó, vì nó "rõ ràng hơn" (ha!) Theo cách đó.


Đây là một giải pháp chính xác, nhưng không đủ ngắn, từ xa:

use strict;
use warnings;

my %short = map { $_ => 1 } qw/the and of to a i it in or is/;
my %count = ();

$count{$_}++ foreach grep { $_ && !$short{$_} } map { split /[^a-zA-Z]/ } (<>);
my @sorted = (sort { $count{$b} <=> $count{$a} } keys %count)[0..21];
my $widest = 76 - (length $sorted[0]);

print " " . ("_" x $widest) . "\n";
foreach (@sorted)
{
    my $width = int(($count{$_} / $count{$sorted[0]}) * $widest);
    print "|" . ("_" x $width) . "| $_ \n";
}

Sau đây là khoảng ngắn như nó có thể nhận được trong khi vẫn còn tương đối dễ đọc. (392 ký tự).

%short = map { $_ => 1 } qw/the and of to a i it in or is/;
%count;

$count{$_}++ foreach grep { $_ && !$short{$_} } map { split /[^a-z]/, lc } (<>);
@sorted = (sort { $count{$b} <=> $count{$a} } keys %count)[0..21];
$widest = 76 - (length $sorted[0]);

print " " . "_" x $widest . "\n";
print"|" . "_" x int(($count{$_} / $count{$sorted[0]}) * $widest) . "| $_ \n" foreach @sorted;

Có một vài lỗi ngay bây giờ; sửa chữa và rút ngắn.
JSB

4
Điều này không bao gồm trường hợp khi từ thứ hai dài hơn từ thứ nhất, phải không?
Joey

1
Cả hai foreachs có thể được viết là fors. Đó là 8 ký tự xuống. Sau đó, bạn có grep{!($_~~@s)}map{lc=~/[a-z]+/g}<>, mà tôi tin rằng có thể được viết là grep{!(/$_/i~~@s)}<>=~/[a-z]+/gđể đi xuống thêm 4. Thay thế " "với $"và bạn xuống thêm 1 ...
Zaid

sort{$c{$b}-$c{$a}}...để tiết kiệm thêm hai. Bạn cũng có thể chỉ cần vượt qua %cthay vì keys %ccho sortchức năng và tiết kiệm thêm bốn.
mob

20

Windows PowerShell, 199 ký tự

$x=$input-split'\P{L}'-notmatch'^(the|and|of|to|.?|i[tns]|or)$'|group|sort *
filter f($w){' '+'_'*$w
$x[-1..-22]|%{"|$('_'*($w*$_.Count/$x[-1].Count))| "+$_.Name}}
f(76..1|?{!((f $_)-match'.'*80)})[0]

(Ngắt dòng cuối cùng là không cần thiết, nhưng bao gồm ở đây để dễ đọc.)

(Mã hiện tại và các tệp thử nghiệm của tôi có sẵn trong kho SVN của tôi . Tôi hy vọng các trường hợp thử nghiệm của tôi bắt được hầu hết các lỗi phổ biến (độ dài thanh, sự cố với kết hợp regex và một vài lỗi khác))

Giả định:

  • ASCII của Mỹ làm đầu vào. Nó có thể trở nên kỳ lạ với Unicode.
  • Ít nhất hai từ không ngừng trong văn bản

Lịch sử

Phiên bản thư giãn (137), vì hiện tại đã được tính riêng:

($x=$input-split'\P{L}'-notmatch'^(the|and|of|to|.?|i[tns]|or)$'|group|sort *)[-1..-22]|%{"|$('_'*(76*$_.Count/$x[-1].Count))| "+$_.Name}
  • không đóng thanh đầu tiên
  • không tính đến độ dài từ của từ không phải từ đầu tiên

Biến thể độ dài thanh của một ký tự so với các giải pháp khác là do PowerShell sử dụng làm tròn thay vì cắt ngắn khi chuyển đổi số dấu phẩy động thành số nguyên. Vì nhiệm vụ chỉ yêu cầu chiều dài thanh tỷ lệ nên điều này là tốt, mặc dù.

So với các giải pháp khác, tôi đã sử dụng một cách tiếp cận hơi khác trong việc xác định độ dài thanh dài nhất bằng cách đơn giản thử và lấy độ dài cao nhất như vậy trong đó không có dòng nào dài hơn 80 ký tự.

Một phiên bản cũ hơn được giải thích có thể được tìm thấy ở đây .


Ấn tượng, dường như Powershell là một môi trường phù hợp để chơi gôn. Cách tiếp cận của bạn xem xét độ dài thanh là chính xác những gì tôi đã cố gắng mô tả (không quá xuất sắc, tôi thừa nhận) trong thông số kỹ thuật.
BarsheD

1
@ChristopheD: Theo kinh nghiệm của tôi (Anarchy Golf, một số nhiệm vụ Project Euler và một số nhiệm vụ khác chỉ để giải trí), PowerShell thường chỉ kém hơn Ruby một chút và thường được gắn với hoặc tốt hơn Perl và Python. Không có trận đấu nào cho GolfScript. Nhưng theo như tôi có thể thấy, đây có thể là giải pháp ngắn nhất chiếm chính xác độ dài thanh ;-)
Joey

Rõ ràng tôi đã đúng. Powershell có thể làm tốt hơn - tốt hơn nhiều! Vui lòng cung cấp một phiên bản mở rộng với ý kiến.
Gabe

Julian: Bạn đã thử -split("\b(?:the|and|of|to|a|i[tns]?|or)\b|[^a-z]")chưa? Nó làm việc cho tôi.
Gabe

Đừng quên nội suy chuỗi đầu ra: "|$('_'*($w*$_.count/$x[0].count))| $($_.name) "(hoặc loại bỏ khoảng trắng cuối cùng, vì nó là loại tự động). Và bạn có thể sử dụng -split("(?:\b(?:the|and|of|to|a|i[tns]?|or)\b|[^a-z])+")để tiết kiệm một vài chi tiết bằng cách không bao gồm khoảng trắng (hoặc sử dụng [-2..-23]).
Gabe

19

Ruby, 215, 216 , 218 , 221 , 224 , 236 , 237 ký tự

cập nhật 1: Hurrah ! Đó là một chiếc cà vạt với JS Bangs ' giải pháp . Không thể nghĩ ra cách nào để cắt giảm nữa :)

cập nhật 2: Chơi một trò đánh golf bẩn. Thay đổieach để maplưu 1 ký tự :)

cập nhật 3: Thay đổi File.readthành IO.read+2.Array.group_bykhông hiệu quả lắm, đổi thànhreduce +6. Không cần kiểm tra không phân biệt chữ hoa chữ thường sau khi đặt dưới với downcaseregex +1. Sắp xếp theo thứ tự giảm dần được thực hiện dễ dàng bằng cách phủ định giá trị +6. Tổng tiết kiệm +15

cập nhật 4: [0] thay vì.first , +3. (@ Shtééf)

cập nhật 5: Mở rộng biến l tại chỗ, +1. Mở rộng biếns tại chỗ, +2. (@ Shtééf)

cập nhật 6: Sử dụng phép cộng chuỗi thay vì nội suy cho dòng đầu tiên, +2. (@ Shtééf)

w=(IO.read($_).downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).reduce(Hash.new 0){|m,o|m[o]+=1;m}.sort_by{|k,v|-v}.take 22;m=76-w[0][0].size;puts' '+'_'*m;w.map{|x,f|puts"|#{'_'*(f*1.0/w[0][1]*m)}| #{x} "}

Cập nhật 7: Tôi đã trải qua rất nhiều hoopla để phát hiện lần lặp đầu tiên bên trong vòng lặp, sử dụng các biến thể hiện. Tất cả tôi nhận được là +1, mặc dù có lẽ có tiềm năng. Bảo tồn phiên bản trước, vì tôi tin rằng đây là ma thuật đen. (@ Shtééf)

(IO.read($_).downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).reduce(Hash.new 0){|m,o|m[o]+=1;m}.sort_by{|k,v|-v}.take(22).map{|x,f|@f||(@f=f;puts' '+'_'*(@m=76-x.size));puts"|#{'_'*(f*1.0/@f*@m)}| #{x} "}

Phiên bản dễ đọc

string = File.read($_).downcase

words = string.scan(/[a-z]+/i)
allowed_words = words - %w{the and of to a i it in or is}
sorted_words = allowed_words.group_by{ |x| x }.map{ |x,y| [x, y.size] }.sort{ |a,b| b[1] <=> a[1] }.take(22)
highest_frequency = sorted_words.first
highest_frequency_count = highest_frequency[1]
highest_frequency_word = highest_frequency[0]

word_length = highest_frequency_word.size
widest = 76 - word_length

puts " #{'_' * widest}"    
sorted_words.each do |word, freq|
  width = (freq * 1.0 / highest_frequency_count) * widest
  puts "|#{'_' * width}| #{word} "
end

Để sử dụng:

echo "Alice.txt" | ruby -ln GolfedWordFrequencies.rb

Đầu ra:

 _________________________________________________________________________
|_________________________________________________________________________| she 
|_______________________________________________________________| you 
|____________________________________________________________| said 
|_____________________________________________________| alice 
|_______________________________________________| was 
|___________________________________________| that 
|____________________________________| as 
|________________________________| her 
|_____________________________| with 
|_____________________________| at 
|____________________________| s 
|____________________________| t 
|__________________________| on 
|__________________________| all 
|_______________________| this 
|_______________________| for 
|_______________________| had 
|_______________________| but 
|______________________| be 
|_____________________| not 
|____________________| they 
|____________________| so 

3
Không phải là "p" một phím tắt cho "đặt"? Điều đó có thể cạo một vài.
rfusca

1
Đẹp. Việc sử dụng của bạn scan, mặc dù, đã cho tôi một ý tưởng tốt hơn, vì vậy tôi đã đi trước một lần nữa :).
JSB

2
Bạn cần chia tỷ lệ các thanh sao cho từ dài nhất cộng với thanh của nó phù hợp với 80 ký tự. Như Brian đề xuất, một từ thứ hai dài sẽ phá vỡ chương trình của bạn.
Gabe

3
Tôi tự hỏi tại sao điều này vẫn đang thu thập phiếu bầu. Giải pháp không chính xác (trong trường hợp chung) và hiện tại các giải pháp Ruby ngắn hơn hai chiều.
Joey

1
Bây giờ, hãy sửa lỗi cho tôi nếu tôi sai, nhưng thay vì sử dụng "chữ thường", tại sao bạn không sử dụng cờ không nhạy cảm trường hợp REGEXP, để tiết kiệm 6-7 byte, phải không?
st0le

19

Python 2.x, cách tiếp cận latitudinary = 227 183 ký tự

import sys,re
t=re.split('\W+',sys.stdin.read().lower())
r=sorted((-t.count(w),w)for w in set(t)if w not in'andithetoforinis')[:22]
for l,w in r:print(78-len(r[0][1]))*l/r[0][0]*'=',w

Cho phép tự do trong việc thực hiện, tôi đã xây dựng một chuỗi nối có chứa tất cả các từ được yêu cầu loại trừ ( the, and, of, to, a, i, it, in, or, is) - cộng với nó cũng loại trừ hai "từ" khét tiếng sttừ ví dụ - và tôi đã ném vào miễn phí loại trừ an, for, he. Tôi đã thử tất cả các từ ghép với các từ trong Alice, Kinh thánh của King James và tệp Jargon để xem liệu có bất kỳ từ nào sẽ bị loại trừ bởi chuỗi. Và đó là cách tôi kết thúc với hai chuỗi loại trừ: itheandtoforinisandithetoforinis.

Tái bút mượn từ các giải pháp khác để rút ngắn mã.

=========================================================================== she 
================================================================= you
============================================================== said
====================================================== alice
================================================ was
============================================ that
===================================== as
================================= her
============================== at
============================== with
=========================== on
=========================== all
======================== this
======================== had
======================= but
====================== be
====================== not
===================== they
==================== so
=================== very
=================== what
================= little

Rant

Về những từ để bỏ qua, người ta sẽ nghĩ những từ đó sẽ được lấy từ danh sách những từ được sử dụng nhiều nhất trong tiếng Anh. Danh sách đó phụ thuộc vào văn bản được sử dụng. Theo một trong những danh sách phổ biến nhất ( http://en.wikipedia.org/wiki/Most_common_words_in_English , http://www.english-for-students.com/Frequently-Used-emme.html , http: // www. sporcle.com/games/common_english_words.php ), 10 từ hàng đầu là:the be(am/are/is/was/were) to of and a in that have I

10 từ hàng đầu từ văn bản Alice in Wonderland là the and to a of it she i you said
10 từ hàng đầu từ Tệp Jargon (v4.4.7) làthe a of to and in is that or for

Vì vậy, câu hỏi là tại sao orđược đưa vào danh sách bỏ qua của vấn đề, trong đó nó phổ biến thứ 30 khi từ này that(thứ 8 được sử dụng nhiều nhất) thì không. vv, do đó tôi tin rằng danh sách bỏ qua nên được cung cấp động (hoặc có thể được bỏ qua).

Ý tưởng thay thế sẽ chỉ đơn giản là bỏ qua 10 từ hàng đầu từ kết quả - mà thực sự sẽ rút ngắn giải pháp (cơ bản - phải chỉ hiển thị các mục thứ 11 đến 32).


Python 2.x, cách tiếp cận đúng giờ = 277 243 ký tự

Biểu đồ được vẽ trong đoạn mã trên được đơn giản hóa (chỉ sử dụng một ký tự cho các thanh). Nếu một người muốn sao chép chính xác biểu đồ từ mô tả vấn đề (không bắt buộc), mã này sẽ thực hiện:

import sys,re
t=re.split('\W+',sys.stdin.read().lower())
r=sorted((-t.count(w),w)for w in set(t)-set(sys.argv))[:22]
h=min(9*l/(77-len(w))for l,w in r)
print'',9*r[0][0]/h*'_'
for l,w in r:print'|'+9*l/h*'_'+'|',w

Tôi có một vấn đề với sự lựa chọn hơi ngẫu nhiên trong số 10 từ để loại trừ the, and, of, to, a, i, it, in, or, isđể những từ đó được truyền dưới dạng tham số dòng lệnh, như vậy:
python WordFrequencyChart.py the and of to a i it in or is <"Alice's Adventures in Wonderland.txt"

Đây là 213 ký tự + 30 nếu chúng tôi chiếm danh sách bỏ qua "gốc" được truyền trên dòng lệnh = 243

Tái bút Mã thứ hai cũng thực hiện "điều chỉnh" độ dài của tất cả các từ hàng đầu, vì vậy không có từ nào trong số chúng sẽ tràn trong trường hợp suy biến.

 _______________________________________________________________
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|_____________________________________________________| said
|______________________________________________| alice
|_________________________________________| was
|______________________________________| that
|_______________________________| as
|____________________________| her
|__________________________| at
|__________________________| with
|_________________________| s
|_________________________| t
|_______________________| on
|_______________________| all
|____________________| this
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|___________________| not
|_________________| they
|_________________| so

Giải pháp tốt đẹp cho đến nay mặc dù danh sách bỏ qua từ chưa được triển khai (chưa) và các thanh hiện tại hơi thô sơ.
BarsheD

@ChristopheD: nó đã ở đó, nhưng không có "hướng dẫn sử dụng". Chỉ cần thêm văn bản bó
Nas Banov

Về danh sách các ngôn ngữ và giải pháp của bạn: Vui lòng tìm kiếm các giải pháp sử dụng phân tách \Whoặc sử dụng \btrong biểu thức chính vì chúng rất có thể không theo thông số kỹ thuật, có nghĩa là chúng sẽ không phân tách trên các chữ số hoặc _chúng cũng có thể không xóa các từ dừng khỏi chuỗi chẳng hạn như the_foo_or123bar. Chúng có thể không xuất hiện trong văn bản thử nghiệm nhưng đặc điểm kỹ thuật khá rõ ràng trong trường hợp đó.
Joey

Công việc tuyệt vời Nas, tôi đã dành một buổi chiều cố gắng tối ưu hóa điều này và chỉ tìm thấy một cải tiến. Bạn có thể cắt nó xuống còn 239 ký tự bằng cách xóa sys.argvhack và sử dụng:re.findall(r'\b(?!(?:the|and|.|of|to|i[tns]|or)\b)\w+',sys.stdin.read().lower())
intgr

12

Haskell - 366 351 344 337 333 ký tự

(Một dòng ngắt mainđược thêm vào để dễ đọc và không cần ngắt dòng ở cuối dòng cuối cùng.)

import Data.List
import Data.Char
l=length
t=filter
m=map
f c|isAlpha c=toLower c|0<1=' '
h w=(-l w,head w)
x!(q,w)='|':replicate(minimum$m(q?)x)'_'++"| "++w
q?(g,w)=q*(77-l w)`div`g
b x=m(x!)x
a(l:r)=(' ':t(=='_')l):l:r
main=interact$unlines.a.b.take 22.sort.m h.group.sort
  .t(`notElem`words"the and of to a i it in or is").words.m f

Làm thế nào nó hoạt động được nhìn thấy tốt nhất bằng cách đọc các đối số để interactngược lại:

  • map f chữ cái thường, thay thế mọi thứ khác bằng không gian.
  • words tạo ra một danh sách các từ, bỏ khoảng trắng tách biệt.
  • filter (khôngwords "the and of to a i it in or is") loại bỏ tất cả các mục với các từ bị cấm.
  • group . sort sắp xếp các từ và nhóm các từ giống hệt nhau vào danh sách.
  • map h ánh xạ mỗi danh sách các từ giống hệt nhau đến một bộ mẫu (-frequency, word) .
  • take 22 . sort sắp xếp các bộ dữ liệu theo tần số giảm dần (mục nhập bộ dữ liệu đầu tiên) và chỉ giữ 22 bộ dữ liệu đầu tiên.
  • b ánh xạ tuples vào thanh (xem bên dưới).
  • a chuẩn bị dòng đầu tiên của dấu gạch dưới, để hoàn thành thanh trên cùng.
  • unlines tham gia tất cả các dòng này cùng với dòng mới.

Các mẹo nhỏ là có được chiều dài thanh đúng. Tôi giả sử rằng chỉ có dấu gạch dưới được tính theo chiều dài của thanh, vì vậy ||sẽ là một thanh có độ dài bằng không. Các chức năng bánh xạ c xtrên x, nơi xlà danh sách các biểu đồ. Toàn bộ danh sách được chuyển đến c, để mỗi lần gọi ccó thể tính toán hệ số tỷ lệ cho chính nó bằng cách gọiu . Theo cách này, tôi tránh sử dụng toán học dấu phẩy động hoặc các số hữu tỷ, có hàm chuyển đổi và nhập sẽ ăn nhiều ký tự.

Lưu ý mẹo sử dụng -frequency. Điều này loại bỏ sự cần thiết phải reversecác sorttừ sắp xếp (tăng dần) -frequencysẽ nơi những lời với tần số lớn nhất đầu tiên. Sau đó, trong hàm u, hai -frequencygiá trị được nhân lên, sẽ hủy bỏ phủ định.


Công việc rất tốt (sẽ upvote nhưng hết phiếu cho ngày hôm nay với tất cả các câu trả lời tuyệt vời trong chủ đề này).
BarsheD

Điều này làm tổn thương đôi mắt của tôi theo cách thậm chí đau đớn khi nghĩ về việc mô tả, nhưng tôi đã học được rất nhiều Haskell bằng cách chuyển đổi nó thành mã rõ ràng. Làm tốt lắm, thưa ngài. :-)
Owen S.

Nó thực sự khá Haskell vẫn còn, mặc dù không thực sự hiệu quả. Các tên ngắn làm cho nó trông tồi tệ hơn nhiều so với thực tế.
Thomas

@Thomas: Bạn có thể nói lại lần nữa. :-)
Owen S.

1
Không thể di chuyển div, thực sự! Hãy thử nó - đầu ra là sai. Lý do là làm divtrước khi *mất độ chính xác.
MtnViewMark

11

JavaScript 1.8 (SpiderMonkey) - 354

x={};p='|';e=' ';z=[];c=77
while(l=readline())l.toLowerCase().replace(/\b(?!(the|and|of|to|a|i[tns]?|or)\b)\w+/g,function(y)x[y]?x[y].c++:z.push(x[y]={w:y,c:1}))
z=z.sort(function(a,b)b.c-a.c).slice(0,22)
for each(v in z){v.r=v.c/z[0].c
c=c>(l=(77-v.w.length)/v.r)?l:c}for(k in z){v=z[k]
s=Array(v.r*c|0).join('_')
if(!+k)print(e+s+e)
print(p+s+p+e+v.w)}

Đáng buồn thay, for([k,v]in z)từ phiên bản Rhino dường như không muốn hoạt động trong SpiderMonkey, và readFile()dễ dàng hơn một chút so với sử dụngreadline() nhưng việc di chuyển lên 1.8 cho phép chúng tôi sử dụng các chức năng đóng để cắt thêm một vài dòng ....

Thêm khoảng trắng cho dễ đọc:

x={};p='|';e=' ';z=[];c=77
while(l=readline())
  l.toLowerCase().replace(/\b(?!(the|and|of|to|a|i[tns]?|or)\b)\w+/g,
   function(y) x[y] ? x[y].c++ : z.push( x[y] = {w: y, c: 1} )
  )
z=z.sort(function(a,b) b.c - a.c).slice(0,22)
for each(v in z){
  v.r=v.c/z[0].c
  c=c>(l=(77-v.w.length)/v.r)?l:c
}
for(k in z){
  v=z[k]
  s=Array(v.r*c|0).join('_')
  if(!+k)print(e+s+e)
  print(p+s+p+e+v.w)
}

Sử dụng: js golf.js < input.txt

Đầu ra:

 Giới thiệu 
| _________________________________________________________________________ | bà ấy
| _____________________________________________________________ | bạn
| ____________________________________________________________ | nói
| ____________________________________________________ | alice
| ____________________________________________ | là
| cái đó
| như
| cô ấy
| tại
| với
| S
| t
| trên
| tất cả
| _______________ | điều này
| cho
| đã có
| nhưng
| là
| không phải
| họ
| vì thế

(phiên bản cơ sở - không xử lý chính xác độ rộng thanh)

JavaScript (Tê giác) - 405 395 387 377 368 343 304 ký tự

Tôi nghĩ logic sắp xếp của tôi bị tắt, nhưng .. tôi duno. Brainfart cố định.

Giảm thiểu (lạm dụng \nđược hiểu là ;đôi khi):

x={};p='|';e=' ';z=[]
readFile(arguments[0]).toLowerCase().replace(/\b(?!(the|and|of|to|a|i[tns]?|or)\b)\w+/g,function(y){x[y]?x[y].c++:z.push(x[y]={w:y,c:1})})
z=z.sort(function(a,b){return b.c-a.c}).slice(0,22)
for([k,v]in z){s=Array((v.c/z[0].c)*70|0).join('_')
if(!+k)print(e+s+e)
print(p+s+p+e+v.w)}

À, thưa ngài. Tôi tin rằng đây là găng tay của bạn. Có lần thứ hai nói chuyện với tôi.
dmckee --- ex-moderator mèo con

2
BTW-- Tôi thích i[tns]?bit. Rất lén lút.
dmckee --- ex-moderator mèo con

@dmckee - Chơi tốt, tôi không nghĩ mình có thể đánh bại 336 của bạn, hãy tận hưởng sự thăng hoa xứng đáng của bạn :)
Matt

Bạn chắc chắn có thể đánh bại 336 ... Có sẵn một cắt giảm 23 ký tự - .replace(/[^\w ]/g, e).split(/\s+/).map(có thể được thay thế bằng .replace(/\w+/g,và sử dụng cùng chức năng mà bạn .mapđã làm ... Cũng không chắc Rhino có hỗ trợ function(a,b)b.c-a.cthay vì chức năng sắp xếp của bạn không (spidermonkey), nhưng điều đó sẽ cạo râu {return }... b.c-a.clà một loại tốt hơn mà a.c<b.cbtw ... Chỉnh sửa phiên bản Spidermonkey ở phía dưới với những thay đổi này
gnarf

Tôi đã chuyển phiên bản SpiderMonkey của mình lên trên cùng vì nó phù hợp với ràng buộc về chiều rộng của thanh ... Cũng được quản lý để cắt thêm một vài ký tự trong phiên bản gốc của bạn bằng cách sử dụng biểu thức regrecead tiêu cực để từ chối cho phép một từ thay thế (), và chơi gôn một vài if với ?:cơ sở tuyệt vời để làm việc mặc dù!
gnarf

11

Phiên bản PHP CLI (450 ký tự)

Giải pháp này có tính đến yêu cầu cuối cùng mà hầu hết những người theo chủ nghĩa thuần túy đã chọn lựa bỏ qua. Điều đó có giá 170 ký tự!

Sử dụng: php.exe <this.php> <file.txt>

Giảm thiểu:

<?php $a=array_count_values(array_filter(preg_split('/[^a-z]/',strtolower(file_get_contents($argv[1])),-1,1),function($x){return !preg_match("/^(.|the|and|of|to|it|in|or|is)$/",$x);}));arsort($a);$a=array_slice($a,0,22);function R($a,$F,$B){$r=array();foreach($a as$x=>$f){$l=strlen($x);$r[$x]=$b=$f*$B/$F;if($l+$b>76)return R($a,$f,76-$l);}return$r;}$c=R($a,max($a),76-strlen(key($a)));foreach($a as$x=>$f)echo '|',str_repeat('-',$c[$x]),"| $x\n";?>

Con người có thể đọc được:

<?php

// Read:
$s = strtolower(file_get_contents($argv[1]));

// Split:
$a = preg_split('/[^a-z]/', $s, -1, PREG_SPLIT_NO_EMPTY);

// Remove unwanted words:
$a = array_filter($a, function($x){
       return !preg_match("/^(.|the|and|of|to|it|in|or|is)$/",$x);
     });

// Count:
$a = array_count_values($a);

// Sort:
arsort($a);

// Pick top 22:
$a=array_slice($a,0,22);


// Recursive function to adjust bar widths
// according to the last requirement:
function R($a,$F,$B){
    $r = array();
    foreach($a as $x=>$f){
        $l = strlen($x);
        $r[$x] = $b = $f * $B / $F;
        if ( $l + $b > 76 )
            return R($a,$f,76-$l);
    }
    return $r;
}

// Apply the function:
$c = R($a,max($a),76-strlen(key($a)));


// Output:
foreach ($a as $x => $f)
    echo '|',str_repeat('-',$c[$x]),"| $x\n";

?>

Đầu ra:

|-------------------------------------------------------------------------| she
|---------------------------------------------------------------| you
|------------------------------------------------------------| said
|-----------------------------------------------------| alice
|-----------------------------------------------| was
|-------------------------------------------| that
|------------------------------------| as
|--------------------------------| her
|-----------------------------| at
|-----------------------------| with
|--------------------------| on
|--------------------------| all
|-----------------------| this
|-----------------------| for
|-----------------------| had
|-----------------------| but
|----------------------| be
|---------------------| not
|--------------------| they
|--------------------| so
|-------------------| very
|------------------| what

Khi có một từ dài, các thanh được điều chỉnh đúng:

|--------------------------------------------------------| she
|---------------------------------------------------| thisisareallylongwordhere
|-------------------------------------------------| you
|-----------------------------------------------| said
|-----------------------------------------| alice
|------------------------------------| was
|---------------------------------| that
|---------------------------| as
|-------------------------| her
|-----------------------| with
|-----------------------| at
|--------------------| on
|--------------------| all
|------------------| this
|------------------| for
|------------------| had
|-----------------| but
|-----------------| be
|----------------| not
|---------------| they
|---------------| so
|--------------| very

11

Python 3.1 - 245 229 charaters

Tôi đoán sử dụng Counter là một loại gian lận :) Tôi mới đọc về nó khoảng một tuần trước, vì vậy đây là cơ hội hoàn hảo để xem nó hoạt động như thế nào.

import re,collections
o=collections.Counter([w for w in re.findall("[a-z]+",open("!").read().lower())if w not in"a and i in is it of or the to".split()]).most_common(22)
print('\n'.join('|'+76*v//o[0][1]*'_'+'| '+k for k,v in o))

In ra:

|____________________________________________________________________________| she
|__________________________________________________________________| you
|_______________________________________________________________| said
|_______________________________________________________| alice
|_________________________________________________| was
|_____________________________________________| that
|_____________________________________| as
|__________________________________| her
|_______________________________| with
|_______________________________| at
|______________________________| s
|_____________________________| t
|____________________________| on
|___________________________| all
|________________________| this
|________________________| for
|________________________| had
|________________________| but
|______________________| be
|______________________| not
|_____________________| they
|____________________| so

Một số mã được "mượn" từ giải pháp của AKX.


Dòng đầu tiên bị thiếu. Và chiều dài thanh không chính xác.
Joey

trong mã của bạn có vẻ như open('!')đọc từ stdin - đó là phiên bản / HĐH nào? hoặc bạn phải đặt tên cho tệp '!'?
Nas Banov

Đặt tên cho tệp "!" :) Xin lỗi đó là không rõ ràng, và tôi nên đã đề cập đến nó.
Sam Dolan

11

perl, 205 191 189 ký tự / 205 ký tự (thực hiện đầy đủ)

Một số phần được lấy cảm hứng từ các bài nộp perl / ruby ​​trước đó, một vài ý tưởng tương tự đã được đưa ra một cách độc lập, những phần khác là nguyên bản. Phiên bản ngắn hơn cũng kết hợp một số điều tôi đã thấy / học được từ các bài nộp khác.

Nguyên:

$k{$_}++for grep{$_!~/^(the|and|of|to|a|i|it|in|or|is)$/}map{lc=~/[a-z]+/g}<>;@t=sort{$k{$b}<=>$k{$a}}keys%k;$l=76-length$t[0];printf" %s
",'_'x$l;printf"|%s| $_
",'_'x int$k{$_}/$k{$t[0]}*$l for@t[0..21];

Phiên bản mới nhất xuống còn 191 ký tự:

/^(the|and|of|to|.|i[tns]|or)$/||$k{$_}++for map{lc=~/[a-z]+/g}<>;@e=sort{$k{$b}<=>$k{$a}}keys%k;$n=" %s
";$r=(76-y///c)/$k{$_=$e[0]};map{printf$n,'_'x($k{$_}*$r),$_;$n="|%s| %s
"}@e[0,0..21]

Phiên bản mới nhất xuống tới 189 ký tự:

/^(the|and|of|to|.|i[tns]|or)$/||$k{$_}++for map{lc=~/[a-z]+/g}<>;@_=sort{$k{$b}<=>$k{$a}}keys%k;$n=" %s
";$r=(76-m//)/$k{$_=$_[0]};map{printf$n,'_'x($k{$_}*$r),$_;$n="|%s| %s
"}@_[0,0..21]

Phiên bản này (205 char) cho các dòng có từ dài hơn những gì sẽ được tìm thấy sau này.

/^(the|and|of|to|.|i[tns]|or)$/||$k{$_}++for map{lc=~/[a-z]+/g}<>;($r)=sort{$a<=>$b}map{(76-y///c)/$k{$_}}@e=sort{$k{$b}<=>$k{$a}}keys%k;$n=" %s
";map{printf$n,'_'x($k{$_}*$r),$_;$n="|%s| %s
";}@e[0,0..21]

10

Perl: 203 202 201 198 195 208 203/231 ký tự

$/=\0;/^(the|and|of|to|.|i[tns]|or)$/i||$x{lc$_}++for<>=~/[a-z]+/gi;map{$z=$x{$_};$y||{$y=(76-y///c)/$z}&&warn" "."_"x($z*$y)."\n";printf"|%.78s\n","_"x($z*$y)."| $_"}(sort{$x{$b}<=>$x{$a}}keys%x)[0..21]

Thay thế, thực hiện đầy đủ bao gồm cả hành vi được chỉ định (squishing toàn cầu) cho trường hợp bệnh lý trong đó từ thứ hai vừa phổ biến vừa đủ dài để kết hợp với hơn 80 ký tự ( cách thực hiện này là 231 ký tự ):

$/=\0;/^(the|and|of|to|.|i[tns]|or)$/i||$x{lc$_}++for<>=~/[a-z]+/gi;@e=(sort{$x{$b}<=>$x{$a}}keys%x)[0..21];for(@e){$p=(76-y///c)/$x{$_};($y&&$p>$y)||($y=$p)}warn" "."_"x($x{$e[0]}*$y)."\n";for(@e){warn"|"."_"x($x{$_}*$y)."| $_\n"}

Thông số kỹ thuật không nêu bất cứ nơi nào mà điều này phải đến STDOUT, vì vậy tôi đã sử dụng cảnh báo () thay vì in - bốn ký tự được lưu ở đó. Bản đồ được sử dụng thay vì foreach, nhưng tôi cảm thấy như vẫn có thể tiết kiệm được nhiều hơn trong phần tách (tham gia ()). Tuy nhiên, đã giảm xuống còn 203 - có thể ngủ trên đó. Ít nhất là Perl bây giờ dưới số "char, grep, tr, grep, sort, uniq, sort, head, perl" cho đến bây giờ;)

PS: Reddit nói "Xin chào";)

Cập nhật: Đã xóa tham gia () để chuyển nhượng và tham gia chuyển đổi vô hướng ẩn. Xuống tới 202. Ngoài ra, xin lưu ý rằng tôi đã tận dụng quy tắc "bỏ qua các từ 1 chữ cái" tùy chọn để tắt 2 ký tự, vì vậy hãy nhớ rằng tần số sẽ phản ánh điều này.

Cập nhật 2: Hoán đổi chuyển nhượng và tham gia ngầm để giết $ / để lấy tệp trong một ngụm bằng cách sử dụng <> ở vị trí đầu tiên. Cùng kích thước, nhưng nhanh hơn. Trao đổi nếu (! $ Y) {} với $ y || {} &&, đã lưu thêm 1 char => 201.

Cập nhật 3: Kiểm soát việc hạ cấp sớm (lc <>) bằng cách di chuyển lc ra khỏi khối bản đồ - Hoán đổi cả hai biểu thức để không còn sử dụng tùy chọn / i, vì không còn cần thiết. Hoán đổi điều kiện rõ ràng x? Y: z xây dựng cho perlgolf truyền thống | | cấu trúc có điều kiện ngầm định - / ^ ... ... => 198, phá vỡ rào cản 200. Có thể ngủ sớm ... có lẽ.

Cập nhật 4: Thiếu ngủ đã khiến tôi phát điên. Tốt. Điên hơn. Hình dung rằng điều này chỉ phải phân tích các tệp văn bản hạnh phúc bình thường, tôi đã làm cho nó từ bỏ nếu nó không có giá trị. Lưu hai nhân vật. Đã thay thế "độ dài" bằng 1-char ngắn hơn (và nhiều gôn hơn) y /// c - bạn có nghe tôi nói không, GolfScript ?? Tôi đang đến với bạn!!! nức nở

Cập nhật 5: Ngủ dep khiến tôi quên đi giới hạn 22row và giới hạn dòng tiếp theo. Sao lưu lên tới 208 với những người được xử lý. Không quá tệ, 13 ký tự để xử lý nó không phải là kết thúc của thế giới. Chơi xung quanh với eval nội tuyến regex của perl, nhưng gặp khó khăn khi làm cho nó vừa hoạt động vừa tiết kiệm ký tự ... lol. Cập nhật ví dụ để phù hợp với đầu ra hiện tại.

Cập nhật 6: Loại bỏ niềng răng không cần thiết bảo vệ (...) vì kẹo cú pháp ++ cho phép đẩy nó lên chống lại hạnh phúc. Nhờ đầu vào từ Chas. Owens (nhắc nhở bộ não mệt mỏi của tôi), có giải pháp lớp nhân vật i [tns] trong đó. Trở lại xuống 203.

Cập nhật 7: Đã thêm phần công việc thứ hai, thực hiện đầy đủ các thông số kỹ thuật (bao gồm cả hành vi cắt thanh đầy đủ cho các từ dài thứ cấp, thay vì cắt ngắn mà hầu hết mọi người đang làm, dựa trên thông số ban đầu mà không có trường hợp ví dụ bệnh lý)

Ví dụ:

 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|__________________________| on
|__________________________| all
|_______________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| so
|___________________| very
|__________________| what

Thực hiện thay thế trong ví dụ trường hợp bệnh lý:

 _______________________________________________________________
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|____________________________________________________| said
|______________________________________________| alice
|________________________________________| was
|_____________________________________| that
|_______________________________| as
|____________________________| her
|_________________________| with
|_________________________| at
|_______________________| on
|______________________| all
|____________________| this
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|__________________| not
|_________________| they
|_________________| so
|________________| very
|________________| what

Bạn có thể rút ngắn regex cho các từ dừng bằng cách thu gọn is|in|it|ivào i[snt]?- và sau đó không còn sự khác biệt với quy tắc tùy chọn nữa. .
Joey

Ok, bỏ qua một phần của những gì tôi đã nói trước đó. Bỏ qua các từ một chữ cái thực sự là một byte ngắn hơn so với không làm nó.
Joey

Mỗi byte đều có giá trị;) Tôi đã cân nhắc thực hiện thủ thuật dòng mới, nhưng tôi đoán rằng nó thực sự có cùng số byte, ngay cả khi nó có ít ký tự in hơn. Vẫn đang làm việc để xem liệu tôi có thể thu nhỏ nó thêm nữa không :)
Syntaera

À, bình thường hóa trường hợp đã ném tôi trở lại 209. Tôi không thấy những gì tôi có thể cắt giảm. Mặc dù PowerShell thể ngắn hơn Perl. ;-)
Joey

Tôi không thấy nơi bạn giới hạn đầu ra ở 22 từ hàng đầu, cũng như nơi bạn chắc chắn rằng một từ thứ hai dài không bao bọc.
Gabe

9

F #, 452 ký tự

Strightforward: lấy một chuỗi acác cặp đếm từ, tìm hệ số nhân từ đếm trên mỗi cột tốt nhất k, sau đó in kết quả.

let a=
 stdin.ReadToEnd().Split(" .?!,\":;'\r\n".ToCharArray(),enum 1)
 |>Seq.map(fun s->s.ToLower())|>Seq.countBy id
 |>Seq.filter(fun(w,n)->not(set["the";"and";"of";"to";"a";"i";"it";"in";"or";"is"].Contains w))
 |>Seq.sortBy(fun(w,n)-> -n)|>Seq.take 22
let k=a|>Seq.map(fun(w,n)->float(78-w.Length)/float n)|>Seq.min
let u n=String.replicate(int(float(n)*k)-2)"_"
printfn" %s "(u(snd(Seq.nth 0 a)))
for(w,n)in a do printfn"|%s| %s "(u n)w

Ví dụ (Tôi có số lượng freq khác với bạn, không chắc tại sao):

% app.exe < Alice.txt

 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|___________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|____________________________| t
|____________________________| s
|__________________________| on
|_________________________| all
|_______________________| this
|______________________| had
|______________________| for
|_____________________| but
|_____________________| be
|____________________| not
|___________________| they
|__________________| so

Hóa ra giải pháp của riêng tôi thực sự là một chút (do một chút khác biệt), các giải pháp tương ứng bây giờ ;-)
BarsheD

+1 cho việc triển khai tỷ lệ thanh chính xác duy nhất cho đến nay
Rotsor

2
(@Rotsor: Trớ trêu thay, cho rằng của tôi là giải pháp lâu đời nhất.)
Brian

Tôi cá là bạn có thể rút ngắn nó một chút bằng cách hợp nhất các giai đoạn phân tách, bản đồ và bộ lọc. Tôi cũng mong rằng bạn sẽ không cần nhiều như vậy float.
Gabe

Các hàm lồng nhau thường không ngắn hơn sử dụng toán tử đường ống |>?
Joey

8

Python 2.6, 347 ký tự

import re
W,x={},"a and i in is it of or the to".split()
[W.__setitem__(w,W.get(w,0)-1)for w in re.findall("[a-z]+",file("11.txt").read().lower())if w not in x]
W=sorted(W.items(),key=lambda p:p[1])[:22]
bm=(76.-len(W[0][0]))/W[0][1]
U=lambda n:"_"*int(n*bm)
print "".join(("%s\n|%s| %s "%((""if i else" "+U(n)),U(n),w))for i,(w,n)in enumerate(W))

Đầu ra:

 _________________________________________________________________________
|_________________________________________________________________________| she 
|_______________________________________________________________| you 
|____________________________________________________________| said 
|_____________________________________________________| alice 
|_______________________________________________| was 
|___________________________________________| that 
|____________________________________| as 
|________________________________| her 
|_____________________________| with 
|_____________________________| at 
|____________________________| s 
|____________________________| t 
|__________________________| on 
|__________________________| all 
|_______________________| this 
|_______________________| for 
|_______________________| had 
|_______________________| but 
|______________________| be 
|_____________________| not 
|____________________| they 
|____________________| so 

1
Bạn có thể mất dòng bm=(76.-len(W[0][0]))/W[0][1]vì bạn chỉ sử dụng bm một lần (tạo dòng tiếp theo U=lambda n:"_"*int(n*(76.-len(W[0][0]))/W[0][1]), loại bỏ 5 ký tự. Ngoài ra: tại sao bạn sẽ sử dụng tên biến 2 ký tự trong chơi golf mã? ;-)
BarsheD

Trên dòng cuối cùng, không gian sau khi in không cần thiết, hãy tắt một ký tự
BarsheD

1
Không xem xét trường hợp khi từ thường xuyên thứ hai là rất dài, phải không?
Joey

@ChristopheD: Bởi vì tôi đã nhìn chằm chằm vào mã đó quá lâu. : P Bắt tốt. @Johannes: Điều đó cũng có thể được sửa chữa, vâng. Không chắc chắn tất cả các triển khai khác đã làm điều đó khi tôi viết điều này.
AKX

7

* sh (+ curl), giải pháp một phần

Điều này là không đầy đủ, nhưng đối với địa ngục của nó, đây là tần số từ tính một nửa của vấn đề trong 192 byte:

curl -s http://www.gutenberg.org/files/11/11.txt|sed -e 's@[^a-z]@\n@gi'|tr '[:upper:]' '[:lower:]'|egrep -v '(^[^a-z]*$|\b(the|and|of|to|a|i|it|in|or|is)\b)' |sort|uniq -c|sort -n|tail -n 22

7

Gawk - 336 (ban đầu 507) ký tự

(sau khi sửa định dạng đầu ra; sửa điều co thắt; điều chỉnh lại, chỉnh lại lần nữa vì vậy, tìm một nơi khác để lưu một vài cái, nhưng đã trả lại hai cái để sửa lỗi chiều dài thanh)

Heh heh! Tôi đang đứng trước thách thức đối với giải pháp [Matt's JavaScript] [1] ! ;) [trăn của AKX] [2].

Vấn đề dường như gọi ra một ngôn ngữ thực hiện các mảng kết hợp riêng, vì vậy tất nhiên tôi đã chọn một ngôn ngữ có một bộ toán tử thiếu kinh khủng trên chúng. Cụ thể, bạn không thể kiểm soát thứ tự mà awk cung cấp các yếu tố của bản đồ băm, vì vậy tôi liên tục quét toàn bộ bản đồ để tìm mục nhiều nhất hiện tại, in và xóa nó khỏi mảng.

Đó là tất cả không hiệu quả khủng khiếp, với tất cả các môn đánh gôn tôi đã làm cho nó cũng đã trở nên khá khủng khiếp.

Giảm thiểu:

{gsub("[^a-zA-Z]"," ");for(;NF;NF--)a[tolower($NF)]++}
END{split("the and of to a i it in or is",b," ");
for(w in b)delete a[b[w]];d=1;for(w in a){e=a[w]/(78-length(w));if(e>d)d=e}
for(i=22;i;--i){e=0;for(w in a)if(a[w]>e)e=a[x=w];l=a[x]/d-2;
t=sprintf(sprintf("%%%dc",l)," ");gsub(" ","_",t);if(i==22)print" "t;
print"|"t"| "x;delete a[x]}}

ngắt dòng cho rõ ràng: chúng không cần thiết và không nên được tính.


Đầu ra:

$ gawk -f wordfreq.awk.min < 11.txt 
 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|____________________________________________________| alice
|______________________________________________| was
|__________________________________________| that
|___________________________________| as
|_______________________________| her
|____________________________| with
|____________________________| at
|___________________________| s
|___________________________| t
|_________________________| on
|_________________________| all
|______________________| this
|______________________| for
|______________________| had
|_____________________| but
|____________________| be
|____________________| not
|___________________| they
|__________________| so
$ sed 's/you/superlongstring/gI' 11.txt | gawk -f wordfreq.awk.min
 ______________________________________________________________________
|______________________________________________________________________| she
|_____________________________________________________________| superlongstring
|__________________________________________________________| said
|__________________________________________________| alice
|____________________________________________| was
|_________________________________________| that
|_________________________________| as
|______________________________| her
|___________________________| with
|___________________________| at
|__________________________| s
|__________________________| t
|________________________| on
|________________________| all
|_____________________| this
|_____________________| for
|_____________________| had
|____________________| but
|___________________| be
|___________________| not
|__________________| they
|_________________| so

Có thể đọc được; 633 ký tự (ban đầu là 949):

{
    gsub("[^a-zA-Z]"," ");
    for(;NF;NF--)
    a[tolower($NF)]++
}
END{
    # remove "short" words
    split("the and of to a i it in or is",b," ");
    for (w in b) 
    delete a[b[w]];
    # Find the bar ratio
    d=1;
    for (w in a) {
    e=a[w]/(78-length(w));
    if (e>d)
        d=e
    }
    # Print the entries highest count first
    for (i=22; i; --i){               
    # find the highest count
    e=0;
    for (w in a) 
        if (a[w]>e)
        e=a[x=w];
        # Print the bar
    l=a[x]/d-2;
    # make a string of "_" the right length
    t=sprintf(sprintf("%%%dc",l)," ");
    gsub(" ","_",t);
    if (i==22) print" "t;
    print"|"t"| "x;
    delete a[x]
    }
}

Làm việc tốt, tốt, bạn đã bao gồm một phiên bản thụt lề / nhận xét ;-)
BarsheD

7

LISP phổ biến, 670 ký tự

Tôi là người mới sử dụng LISP và đây là một nỗ lực sử dụng bảng băm để đếm (vì vậy có lẽ không phải là phương pháp nhỏ gọn nhất).

(flet((r()(let((x(read-char t nil)))(and x(char-downcase x)))))(do((c(
make-hash-table :test 'equal))(w NIL)(x(r)(r))y)((not x)(maphash(lambda
(k v)(if(not(find k '("""the""and""of""to""a""i""it""in""or""is"):test
'equal))(push(cons k v)y)))c)(setf y(sort y #'> :key #'cdr))(setf y
(subseq y 0(min(length y)22)))(let((f(apply #'min(mapcar(lambda(x)(/(-
76.0(length(car x)))(cdr x)))y))))(flet((o(n)(dotimes(i(floor(* n f)))
(write-char #\_))))(write-char #\Space)(o(cdar y))(write-char #\Newline)
(dolist(x y)(write-char #\|)(o(cdr x))(format t "| ~a~%"(car x))))))
(cond((char<= #\a x #\z)(push x w))(t(incf(gethash(concatenate 'string(
reverse w))c 0))(setf w nil)))))

có thể được chạy trên ví dụ với cat alice.txt | clisp -C golf.lisp.

Ở dạng dễ đọc là

(flet ((r () (let ((x (read-char t nil)))
               (and x (char-downcase x)))))
  (do ((c (make-hash-table :test 'equal))  ; the word count map
       w y                                 ; current word and final word list
       (x (r) (r)))  ; iteration over all chars
       ((not x)

        ; make a list with (word . count) pairs removing stopwords
        (maphash (lambda (k v)
                   (if (not (find k '("" "the" "and" "of" "to"
                                      "a" "i" "it" "in" "or" "is")
                                  :test 'equal))
                       (push (cons k v) y)))
                 c)

        ; sort and truncate the list
        (setf y (sort y #'> :key #'cdr))
        (setf y (subseq y 0 (min (length y) 22)))

        ; find the scaling factor
        (let ((f (apply #'min
                        (mapcar (lambda (x) (/ (- 76.0 (length (car x)))
                                               (cdr x)))
                                y))))
          ; output
          (flet ((outx (n) (dotimes (i (floor (* n f))) (write-char #\_))))
             (write-char #\Space)
             (outx (cdar y))
             (write-char #\Newline)
             (dolist (x y)
               (write-char #\|)
               (outx (cdr x))
               (format t "| ~a~%" (car x))))))

       ; add alphabetic to current word, and bump word counter
       ; on non-alphabetic
       (cond
        ((char<= #\a x #\z)
         (push x w))
        (t
         (incf (gethash (concatenate 'string (reverse w)) c 0))
         (setf w nil)))))

Bạn đã thử cài đặt một macro trình đọc tùy chỉnh để loại bỏ một số kích thước đầu vào chưa?
Aaron

@Aaron thực sự nó không tầm thường đối với tôi ngay cả khi nó chỉ hoạt động ... :-) cho phần chơi golf thực tế tôi chỉ sử dụng các biến một chữ cái và đó là tất cả. Dù sao, bên cạnh mức độ chi tiết cao vốn có trong CL đối với quy mô vấn đề này ("chuỗi" chuỗi "," setf "hoặc" gethash "là kẻ giết người ... trong python, chúng là" + "," = "," [] " ) tôi vẫn cảm thấy điều này tồi tệ hơn nhiều mà tôi đã mong đợi ngay cả ở mức độ logic. Theo một nghĩa nào đó, tôi có cảm giác rằng lisp là ổn, nhưng lisp thông thường là như vậy và điều này ngoài việc đặt tên (đọc lại một nhận xét rất không công bằng vì kinh nghiệm của tôi với CL gần như bằng không).
6502

thật. lược đồ sẽ làm cho việc chơi golf dễ dàng hơn một chút, với không gian tên duy nhất. thay vì nối chuỗi ở khắp mọi nơi, bạn có thể (letrec ((một chuỗi nối thêm) (b gethash)) ... (a "x" "yz") ...)
Aaron

6

C (828)

Nó trông giống như mã bị xáo trộn và sử dụng glib cho chuỗi, danh sách và hàm băm. Char đếm với wc -mnói 828 . Nó không xem xét các từ đơn. Để tính độ dài tối đa của thanh, nó xem xét từ dài nhất có thể trong số tất cả, không chỉ từ đầu tiên 22. Đây có phải là độ lệch so với thông số kỹ thuật không?

Nó không xử lý các lỗi và nó không giải phóng bộ nhớ đã sử dụng.

#include <glib.h>
#define S(X)g_string_##X
#define H(X)g_hash_table_##X
GHashTable*h;int m,w=0,z=0;y(const void*a,const void*b){int*A,*B;A=H(lookup)(h,a);B=H(lookup)(h,b);return*B-*A;}void p(void*d,void*u){int *v=H(lookup)(h,d);if(w<22){g_printf("|");*v=*v*(77-z)/m;while(--*v>=0)g_printf("=");g_printf("| %s\n",d);w++;}}main(c){int*v;GList*l;GString*s=S(new)(NULL);h=H(new)(g_str_hash,g_str_equal);char*n[]={"the","and","of","to","it","in","or","is"};while((c=getchar())!=-1){if(isalpha(c))S(append_c)(s,tolower(c));else{if(s->len>1){for(c=0;c<8;c++)if(!strcmp(s->str,n[c]))goto x;if((v=H(lookup)(h,s->str))!=NULL)++*v;else{z=MAX(z,s->len);v=g_malloc(sizeof(int));*v=1;H(insert)(h,g_strdup(s->str),v);}}x:S(truncate)(s,0);}}l=g_list_sort(H(get_keys)(h),y);m=*(int*)H(lookup)(h,g_list_first(l)->data);g_list_foreach(l,p,NULL);}

Dòng mới được tính là ký tự, nhưng bạn có thể loại bỏ bất kỳ dòng nào không phải là hướng dẫn tiền xử lý. Đối với một golf, tôi sẽ không coi việc giải phóng bộ nhớ là một thực hành tồi.
Stéphan Kochen

ok ... đặt tất cả vào một dòng (mong đợi các macro preproc) và đưa ra một câu thơ mà không cần giải phóng mem (và với hai khoảng trắng khác bị xóa ... một chút cải tiến có thể được thực hiện trên "obfuscation", ví dụ *v=*v*(77-lw)/msẽ cung cấp cho 929. .. nhưng tôi nghĩ nó có thể ổn trừ khi tôi tìm ra cách để làm nó ngắn hơn rất nhiều)
ShinTakezou

Tôi nghĩ rằng bạn có thể chuyển ít nhất int cvào phần mainkhai báo và mainhoàn toàn int(như bất kỳ đối số nào chưa được xử lý, afaik) : main(c){...}. Bạn có thể cũng có thể chỉ viết 0thay vì NULL.
Joey

làm điều đó ... tất nhiên sẽ kích hoạt một số cảnh báo với -Wallhoặc với -std=c99cờ trên ... nhưng tôi cho rằng điều này là vô nghĩa đối với một môn đánh gôn, phải không?
ShinTakezou

uff, xin lỗi vì chỉnh sửa thời gian ngắn, ... Tôi nên đổi Without freeing memory stuff, it reaches 866 (removed some other unuseful space)sang thứ khác để không nghĩ mọi người rằng sự khác biệt với phiên bản bộ nhớ trống là ở chỗ: bây giờ phiên bản không có bộ nhớ trống có rất nhiều nhiều "cải tiến".
ShinTakezou

6

Perl, 185 char

200 (hơi hỏng) 199 197 195 193 187 187 185 ký tự. Hai dòng mới là đáng kể. Tuân thủ thông số kỹ thuật.

map$X{+lc}+=!/^(.|the|and|to|i[nst]|o[rf])$/i,/[a-z]+/gfor<>;
$n=$n>($:=$X{$_}/(76-y+++c))?$n:$:for@w=(sort{$X{$b}-$X{$a}}%X)[0..21];
die map{$U='_'x($X{$_}/$n);" $U
"x!$z++,"|$U| $_
"}@w

Tải dòng đầu tiên đếm số từ hợp lệ vào %X.

Dòng thứ hai tính hệ số tỷ lệ tối thiểu để tất cả các dòng đầu ra sẽ <= 80 ký tự.

Dòng thứ ba (chứa hai ký tự dòng mới) tạo đầu ra.


Điều này sẽ không xóa các từ dừng khỏi các chuỗi như "foo_the_bar". Độ dài của dòng cũng quá dài (đọc lại thông số: "thanh + dấu cách + từ + dấu cách <= 80 ký tự")
Joey

5

Java - 886 865 756 744 742 744 752 742 714 680 ký tự

  • Cập nhật trước 742 đầu tiên : regex được cải thiện, loại bỏ các loại tham số thừa, loại bỏ khoảng trắng thừa.

  • Cập nhật 742> 744 ký tự : đã sửa lỗi hack có độ dài cố định. Nó chỉ phụ thuộc vào từ đầu tiên, không phải từ khác (chưa). Tìm thấy một số nơi để rút ngắn mã ( \\strong regex được thay thế ArrayListthay thế bởi Vector). Bây giờ tôi đang tìm kiếm một cách ngắn để loại bỏ sự phụ thuộc IO của Commons và đọc từ stdin.

  • Cập nhật 744> 752 ký tự : Tôi đã xóa phần phụ thuộc chung. Bây giờ nó đọc từ stdin. Dán văn bản trong stdin và nhấn Ctrl+Zđể có kết quả.

  • Cập nhật 752> 742 ký tự : Tôi đã xóa publicvà một khoảng trắng, tạo tên lớp 1 char thay vì 2 và bây giờ bỏ qua các từ một chữ cái.

  • Cập nhật 742> 714 ký tự : Được cập nhật theo nhận xét của Carl: xóa bài tập dự phòng (742> 730), được thay thế m.containsKey(k)bằng m.get(k)!=null(730> 728), giới thiệu cơ sở của dòng (728> 714).

  • Cập nhật 714> 680 ký tự : Được cập nhật theo nhận xét của Rotsor: tính toán kích thước thanh được cải thiện để loại bỏ việc truyền không cần thiết và cải thiện split()để loại bỏ không cần thiết replaceAll().


import java.util.*;class F{public static void main(String[]a)throws Exception{StringBuffer b=new StringBuffer();for(int c;(c=System.in.read())>0;b.append((char)c));final Map<String,Integer>m=new HashMap();for(String w:b.toString().toLowerCase().split("(\\b(.|the|and|of|to|i[tns]|or)\\b|\\W)+"))m.put(w,m.get(w)!=null?m.get(w)+1:1);List<String>l=new Vector(m.keySet());Collections.sort(l,new Comparator(){public int compare(Object l,Object r){return m.get(r)-m.get(l);}});int c=76-l.get(0).length();String s=new String(new char[c]).replace('\0','_');System.out.println(" "+s);for(String w:l.subList(0,22))System.out.println("|"+s.substring(0,m.get(w)*c/m.get(l.get(0)))+"| "+w);}}

Phiên bản dễ đọc hơn:

import java.util.*;
class F{
 public static void main(String[]a)throws Exception{
  StringBuffer b=new StringBuffer();for(int c;(c=System.in.read())>0;b.append((char)c));
  final Map<String,Integer>m=new HashMap();for(String w:b.toString().toLowerCase().split("(\\b(.|the|and|of|to|i[tns]|or)\\b|\\W)+"))m.put(w,m.get(w)!=null?m.get(w)+1:1);
  List<String>l=new Vector(m.keySet());Collections.sort(l,new Comparator(){public int compare(Object l,Object r){return m.get(r)-m.get(l);}});
  int c=76-l.get(0).length();String s=new String(new char[c]).replace('\0','_');System.out.println(" "+s);
  for(String w:l.subList(0,22))System.out.println("|"+s.substring(0,m.get(w)*c/m.get(l.get(0)))+"| "+w);
 }
}

Đầu ra:

 Giới thiệu
| _________________________________________________________________________ | bà ấy
| _____________________________________________________________ | bạn
| ____________________________________________________________ | nói
| ___________________________________________________ | alice
| _____________________________________________ | là
| cái đó
| như
| cô ấy
| với
| tại
| trên
| tất cả
| _______________ | điều này
| _______________ | cho
| _______________ | đã có
| _______________ | nhưng
| là
| không phải
| họ
| vì thế
| rất
| gì

Thật tuyệt khi Java không có String#join()đóng (chưa).

Chỉnh sửa bởi Rotsor:

Tôi đã thực hiện một số thay đổi cho giải pháp của bạn:

  • Danh sách thay thế bằng một chuỗi []
  • Sử dụng lại đối số 'args' thay vì khai báo mảng String của riêng tôi. Cũng sử dụng nó làm đối số cho .ToArray ()
  • StringBuffer đã thay thế bằng String (vâng, vâng, hiệu suất khủng khiếp)
  • Sắp xếp Java thay thế bằng sắp xếp lựa chọn với tạm dừng sớm (chỉ có 22 phần tử đầu tiên được tìm thấy)
  • Tổng hợp một số khai báo int thành một câu lệnh
  • Đã thực hiện thuật toán không gian lận để tìm ra dòng đầu ra hạn chế nhất. Thực hiện nó mà không cần FP.
  • Đã khắc phục sự cố chương trình bị sập khi có ít hơn 22 từ riêng biệt trong văn bản
  • Đã triển khai một thuật toán đọc đầu vào mới, nhanh và chỉ dài hơn 9 ký tự so với tốc độ chậm.

Mã cô đặc có độ dài 688 711 684 ký tự:

import java.util.*;class F{public static void main(String[]l)throws Exception{Map<String,Integer>m=new HashMap();String w="";int i=0,k=0,j=8,x,y,g=22;for(;(j=System.in.read())>0;w+=(char)j);for(String W:w.toLowerCase().split("(\\b(.|the|and|of|to|i[tns]|or)\\b|\\W)+"))m.put(W,m.get(W)!=null?m.get(W)+1:1);l=m.keySet().toArray(l);x=l.length;if(x<g)g=x;for(;i<g;++i)for(j=i;++j<x;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}for(;k<g;k++){x=76-l[k].length();y=m.get(l[k]);if(k<1||y*i>x*j){i=x;j=y;}}String s=new String(new char[m.get(l[0])*i/j]).replace('\0','_');System.out.println(" "+s);for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/j)+"| "+w);}}}

Phiên bản nhanh ( 720 693 ký tự)

import java.util.*;class F{public static void main(String[]l)throws Exception{Map<String,Integer>m=new HashMap();String w="";int i=0,k=0,j=8,x,y,g=22;for(;j>0;){j=System.in.read();if(j>90)j-=32;if(j>64&j<91)w+=(char)j;else{if(!w.matches("^(|.|THE|AND|OF|TO|I[TNS]|OR)$"))m.put(w,m.get(w)!=null?m.get(w)+1:1);w="";}}l=m.keySet().toArray(l);x=l.length;if(x<g)g=x;for(;i<g;++i)for(j=i;++j<x;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}for(;k<g;k++){x=76-l[k].length();y=m.get(l[k]);if(k<1||y*i>x*j){i=x;j=y;}}String s=new String(new char[m.get(l[0])*i/j]).replace('\0','_');System.out.println(" "+s);for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/j)+"| "+w);}}}

Phiên bản dễ đọc hơn:

import java.util.*;class F{public static void main(String[]l)throws Exception{
    Map<String,Integer>m=new HashMap();String w="";
    int i=0,k=0,j=8,x,y,g=22;
    for(;j>0;){j=System.in.read();if(j>90)j-=32;if(j>64&j<91)w+=(char)j;else{
        if(!w.matches("^(|.|THE|AND|OF|TO|I[TNS]|OR)$"))m.put(w,m.get(w)!=null?m.get(w)+1:1);w="";
    }}
    l=m.keySet().toArray(l);x=l.length;if(x<g)g=x;
    for(;i<g;++i)for(j=i;++j<x;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}
    for(;k<g;k++){x=76-l[k].length();y=m.get(l[k]);if(k<1||y*i>x*j){i=x;j=y;}}
    String s=new String(new char[m.get(l[0])*i/j]).replace('\0','_');
    System.out.println(" "+s);
    for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/j)+"| "+w);}}
}

Phiên bản không có cải tiến hành vi là 615 ký tự:

import java.util.*;class F{public static void main(String[]l)throws Exception{Map<String,Integer>m=new HashMap();String w="";int i=0,k=0,j=8,g=22;for(;j>0;){j=System.in.read();if(j>90)j-=32;if(j>64&j<91)w+=(char)j;else{if(!w.matches("^(|.|THE|AND|OF|TO|I[TNS]|OR)$"))m.put(w,m.get(w)!=null?m.get(w)+1:1);w="";}}l=m.keySet().toArray(l);for(;i<g;++i)for(j=i;++j<l.length;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}i=76-l[0].length();String s=new String(new char[i]).replace('\0','_');System.out.println(" "+s);for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/m.get(l[0]))+"| "+w);}}}

Bạn không thể sử dụng tên đủ điều kiện để IOUtilsthay vì nhập nó? Theo như tôi có thể thấy bạn chỉ sử dụng nó một lần.
Joey

5
Bạn bị lừa bằng cách giả sử rằng thanh dài nhất sẽ có chính xác 75 ký tự. Bạn phải chắc chắn rằng không có thanh + từ nào dài hơn 80 ký tự.
Gabe

Bạn đang thiếu một khoảng trống sau từ. ;)
st0le

Khi tôi đang cắt giảm câu trả lời của mình , tôi đã hy vọng tôi sẽ đánh bại sự phục tùng của BalusC. Tôi vẫn còn 200 ký tự, ugh! Tôi tự hỏi điều này sẽ kéo dài bao lâu nếu không có giả định của Commons IO & 75 char.
Jonathon Faust

1
Có vẻ như bạn có thể cạo một số ký tự bằng cách tạo bChuỗi thay vì StringBuffer. Tuy nhiên, tôi không muốn nghĩ về hiệu suất sẽ như thế nào (đặc biệt là khi bạn thêm một ký tự một lần).
Michael Myers

4

Scala 2.8, 311 314 320 330 332 336 341 375 ký tự

bao gồm điều chỉnh từ dài. Ý tưởng mượn từ các giải pháp khác.

Bây giờ là tập lệnh ( a.scala):

val t="\\w+\\b(?<!\\bthe|and|of|to|a|i[tns]?|or)".r.findAllIn(io.Source.fromFile(argv(0)).mkString.toLowerCase).toSeq.groupBy(w=>w).mapValues(_.size).toSeq.sortBy(-_._2)take 22
def b(p:Int)="_"*(p*(for((w,c)<-t)yield(76.0-w.size)/c).min).toInt
println(" "+b(t(0)._2))
for(p<-t)printf("|%s| %s \n",b(p._2),p._1)

Chạy với

scala -howtorun:script a.scala alice.txt

BTW, chỉnh sửa từ 314 đến 311 ký tự thực sự chỉ xóa 1 ký tự. Ai đó đã đếm sai trước đây (Windows CRs?).


4

Clojure 282 nghiêm ngặt

(let[[[_ m]:as s](->>(slurp *in*).toLowerCase(re-seq #"\w+\b(?<!\bthe|and|of|to|a|i[tns]?|or)")frequencies(sort-by val >)(take 22))[b](sort(map #(/(- 76(count(key %)))(val %))s))p #(do(print %1)(dotimes[_(* b %2)](print \_))(apply println %&))](p " " m)(doseq[[k v]s](p \| v \| k)))

Một cách rõ ràng hơn:

(let[[[_ m]:as s](->> (slurp *in*)
                   .toLowerCase
                   (re-seq #"\w+\b(?<!\bthe|and|of|to|a|i[tns]?|or)")
                   frequencies
                   (sort-by val >)
                   (take 22))
     [b] (sort (map #(/ (- 76 (count (key %)))(val %)) s))
     p #(do
          (print %1)
          (dotimes[_(* b %2)] (print \_))
          (apply println %&))]
  (p " " m)
  (doseq[[k v] s] (p \| v \| k)))

4

Scala, 368 ký tự

Đầu tiên, một phiên bản dễ đọc với 592 ký tự:

object Alice {
  def main(args:Array[String]) {
    val s = io.Source.fromFile(args(0))
    val words = s.getLines.flatMap("(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r.findAllIn(_)).map(_.toLowerCase)
    val freqs = words.foldLeft(Map[String, Int]())((countmap, word)  => countmap + (word -> (countmap.getOrElse(word, 0)+1)))
    val sortedFreqs = freqs.toList.sort((a, b)  => a._2 > b._2)
    val top22 = sortedFreqs.take(22)
    val highestWord = top22.head._1
    val highestCount = top22.head._2
    val widest = 76 - highestWord.length
    println(" " + "_" * widest)
    top22.foreach(t => {
      val width = Math.round((t._2 * 1.0 / highestCount) * widest).toInt
      println("|" + "_" * width + "| " + t._1)
    })
  }
}

Đầu ra giao diện điều khiển trông như thế này:

$ scalac alice.scala 
$ scala Alice aliceinwonderland.txt
 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| at
|______________________________| with
|_____________________________| s
|_____________________________| t
|___________________________| on
|__________________________| all
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
|___________________| very
|___________________| what

Chúng tôi có thể thực hiện một số thao tác giảm thiểu mạnh mẽ và giảm xuống còn 415 ký tự:

object A{def main(args:Array[String]){val l=io.Source.fromFile(args(0)).getLines.flatMap("(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r.findAllIn(_)).map(_.toLowerCase).foldLeft(Map[String, Int]())((c,w)=>c+(w->(c.getOrElse(w,0)+1))).toList.sort((a,b)=>a._2>b._2).take(22);println(" "+"_"*(76-l.head._1.length));l.foreach(t=>println("|"+"_"*Math.round((t._2*1.0/l.head._2)*(76-l.head._1.length)).toInt+"| "+t._1))}}

Phiên giao diện điều khiển trông như thế này:

$ scalac a.scala 
$ scala A aliceinwonderland.txt
 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| at
|______________________________| with
|_____________________________| s
|_____________________________| t
|___________________________| on
|__________________________| all
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
|___________________| very
|___________________| what

Tôi chắc rằng một chuyên gia Scala có thể làm tốt hơn nữa.

Cập nhật: Trong các bình luận, Thomas đã đưa ra một phiên bản thậm chí còn ngắn hơn, ở mức 368 ký tự:

object A{def main(a:Array[String]){val t=(Map[String, Int]()/:(for(x<-io.Source.fromFile(a(0)).getLines;y<-"(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r findAllIn x) yield y.toLowerCase).toList)((c,x)=>c+(x->(c.getOrElse(x,0)+1))).toList.sortBy(_._2).reverse.take(22);val w=76-t.head._1.length;print(" "+"_"*w);t map (s=>"\n|"+"_"*(s._2*w/t.head._2)+"| "+s._1) foreach print}}

Rõ ràng, ở 375 ký tự:

object Alice {
  def main(a:Array[String]) {
    val t = (Map[String, Int]() /: (
      for (
        x <- io.Source.fromFile(a(0)).getLines
        y <- "(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r.findAllIn(x)
      ) yield y.toLowerCase
    ).toList)((c, x) => c + (x -> (c.getOrElse(x, 0) + 1))).toList.sortBy(_._2).reverse.take(22)
    val w = 76 - t.head._1.length
    print (" "+"_"*w)
    t.map(s => "\n|" + "_" * (s._2 * w / t.head._2) + "| " + s._1).foreach(print)
  }
}

383 ký tự:object A{def main(a:Array[String]){val t=(Map[String, Int]()/:(for(x<-io.Source.fromFile(a(0)).getLines;y<-"(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r findAllIn x) yield y.toLowerCase).toList)((c,x)=>c+(x->(c.getOrElse(x,0)+1))).toList.sortBy(_._2).reverse.take(22);val w=76-t.head._1.length;print(" "+"_"*w);t map (s=>"\n|"+"_"*(s._2*w/t.head._2)+"| "+s._1) foreach print}}
Thomas Jung

Tất nhiên, tiện dụng cho việc hiểu! Đẹp!
pr1001

3

Java - 896 ký tự

931 ký tự

1233 ký tự không thể đọc được

1977 chars "không nén"


Cập nhật: Tôi đã giảm mạnh số lượng nhân vật. Bỏ qua các từ đơn lẻ trên mỗi thông số cập nhật.

Tôi ghen tị với C # và LINQ rất nhiều.

import java.util.*;import java.io.*;import static java.util.regex.Pattern.*;class g{public static void main(String[] a)throws Exception{PrintStream o=System.out;Map<String,Integer> w=new HashMap();Scanner s=new Scanner(new File(a[0])).useDelimiter(compile("[^a-z]+|\\b(the|and|of|to|.|it|in|or|is)\\b",2));while(s.hasNext()){String z=s.next().trim().toLowerCase();if(z.equals(""))continue;w.put(z,(w.get(z)==null?0:w.get(z))+1);}List<Integer> v=new Vector(w.values());Collections.sort(v);List<String> q=new Vector();int i,m;i=m=v.size()-1;while(q.size()<22){for(String t:w.keySet())if(!q.contains(t)&&w.get(t).equals(v.get(i)))q.add(t);i--;}int r=80-q.get(0).length()-4;String l=String.format("%1$0"+r+"d",0).replace("0","_");o.println(" "+l);o.println("|"+l+"| "+q.get(0)+" ");for(i=m-1;i>m-22;i--){o.println("|"+l.substring(0,(int)Math.round(r*(v.get(i)*1.0)/v.get(m)))+"| "+q.get(m-i)+" ");}}}

"Có thể đọc được":

import java.util.*;
import java.io.*;
import static java.util.regex.Pattern.*;
class g
{
   public static void main(String[] a)throws Exception
      {
      PrintStream o = System.out;
      Map<String,Integer> w = new HashMap();
      Scanner s = new Scanner(new File(a[0]))
         .useDelimiter(compile("[^a-z]+|\\b(the|and|of|to|.|it|in|or|is)\\b",2));
      while(s.hasNext())
      {
         String z = s.next().trim().toLowerCase();
         if(z.equals(""))
            continue;
         w.put(z,(w.get(z) == null?0:w.get(z))+1);
      }
      List<Integer> v = new Vector(w.values());
      Collections.sort(v);
      List<String> q = new Vector();
      int i,m;
      i = m = v.size()-1;
      while(q.size()<22)
      {
         for(String t:w.keySet())
            if(!q.contains(t)&&w.get(t).equals(v.get(i)))
               q.add(t);
         i--;
      }
      int r = 80-q.get(0).length()-4;
      String l = String.format("%1$0"+r+"d",0).replace("0","_");
      o.println(" "+l);
      o.println("|"+l+"| "+q.get(0)+" ");
      for(i = m-1; i > m-22; i--)
      {
         o.println("|"+l.substring(0,(int)Math.round(r*(v.get(i)*1.0)/v.get(m)))+"| "+q.get(m-i)+" ");
      }
   }
}

Đầu ra của Alice:

 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| with
|______________________________| at
|___________________________| on
|__________________________| all
|________________________| this
|________________________| for
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
|___________________| very
|___________________| what

Đầu ra của Don Quixote (cũng từ Gutenberg):

 ________________________________________________________________________
|________________________________________________________________________| that
|________________________________________________________| he
|______________________________________________| for
|__________________________________________| his
|________________________________________| as
|__________________________________| with
|_________________________________| not
|_________________________________| was
|________________________________| him
|______________________________| be
|___________________________| don
|_________________________| my
|_________________________| this
|_________________________| all
|_________________________| they
|________________________| said
|_______________________| have
|_______________________| me
|______________________| on
|______________________| so
|_____________________| you
|_____________________| quixote

8
Toàn bộ cá chép, có thực sự không có cách nào để làm cho nó ngắn hơn trong Java? Tôi hy vọng các bạn được trả tiền theo số lượng nhân vật chứ không phải theo chức năng :-)
Nas Banov
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.