크레이지 사서의 놀라운 분류 시스템


21

학교 시즌으로 돌아 왔습니다! 아르바이트를 위해 학교 도서관에서 도움을 받고 있습니다. 문제는 헤드 사서가 "Dewey Decimal"이라는 단어를 들어 본 적이 없다는 것입니다. 대신, 라이브러리가 확장됨에 따라 사용중인 정렬 시스템이 "유기적으로"커졌습니다.

정신 건강을 유지하기 위해 책을 잘못 정렬하면 책을 돌려 줄 때 도움이되는 프로그램을 작성하기로 결정했습니다. (본 사서는 매우 엄격합니다.)

입출력

  • 입력은 STDIN / 언어에 해당하는 (가설 적) 책 제목 (한 줄에 하나씩) 목록입니다.
  • 한 번에 100 권 이하의 책을 입력 할 수 있습니다 (라이브러리 주변에는 한 번에 너무 많은 책을 소지 할 수 있습니다).
  • 책에는 제목에 여러 단어가있을 수 있으며 이러한 단어는 공백이나 다른 문장 부호 (예 : 콜론 :, 대시 -등) 로 구분할 수 있습니다 .
  • 계산이 쉽도록 모든 제목이 UTF-8이라고 가정하십시오.

출력은 동일한 제목이며, 아래 규칙에 따라 다시 한 줄에 하나씩 STDOUT / 언어로 분류됩니다.

정렬 규칙

책은 평균 문자 값 (즉, 책 제목의 문자 수를 나눈 누적 문자 값)에 따라 숫자로 정렬되며 다음 규칙에 따라 계산됩니다.

  • 모든 문자는 제목의 문자 수를 결정하기 위해 계산됩니다.
  • 소문자는 알파벳에서의 위치로 계산됩니다. (a = 1, b = 2, ... z = 26)
  • 제목에 대문자가 포함 된 경우 소문자 값이 1.5로 계산됩니다 (A = 1.5, B = 3, ... Z = 39). 사서는“자본 문자가 중요합니다!”라고 말합니다.
  • 이 목록의 각 문장 부호 / 기호는 !@#$%^&*()-=_+[]\{}|;':",./<>?~평균을 계산하기 전에 누적 값에서 -1을 계산합니다. ( "Grandiose 타이틀은 아닙니다!")
  • 제목에 아라비아 숫자로 작성된 숫자가 포함 된 경우 정렬하기 전에 해당 숫자가 평균값에서 빼집니다. 여러 개의 연속 숫자는 하나의 숫자로 취급됩니다 (예 : 424를 빼고 2를 빼지 않고 42를 뺍니다). 개별 숫자는 누적 값으로 계산되지 않으며 (즉, 각 숫자는 0을 제공함) DO 문자 수는 계산합니다. 이는 음수 값을 초래할 수 있으므로 적절하게 처리해야합니다. (소문에 따르면, 사서는 현재 수년간 수학 강사에게 호감을 가졌습니다.)
  • 제목에으로 시작하는 두 개의 개별 단어가 포함 된 경우, R책은 "무한대"점수를 받고 모퉁이의 더미에 덤핑됩니다 (즉, 목록의 끝에 임의로 정렬 됨). (사서에는 이니셜이있는 사람이 한 번 버려 두었으므로 들었습니다.)
  • 공백은 누적 문자 값 (즉, 0을 기여)으로 계산하지 않지만 DO는 제목의 문자 수에 기여합니다.
  • 위 규칙에 맞지 않는 문자 (예 : a ÿ)는 누적 문자 값 (즉, 0을 기여)에 포함되지 않지만 DO는 제목의 문자 수에 기여합니다.
  • 예를 들어, 가상 책 ÿÿÿÿÿ은 "점수"를 (0+0+0+0+0) / 5 = 0갖지만 가상 책 ÿÿyÿÿ은 "점수"를 갖습니다 (0+0+25+0+0) / 5 = 5.
  • 동일한 점수를 매기는 두 권의 책을 원하는 순서대로 출력 할 수 있습니다. (어쨌든 그들은 같은 선반에 있습니다)

입력 예 1

War and Peace
Reading Rainbow: The Best Unicorn Ever
Maus
Home for a Bunny

출력 예 1 (추론을 표시하기 위해 괄호 안에 "점수"가 있음-인쇄 할 필요가 없음)

War and Peace (8.5)
Home for a Bunny (10.125)
Maus (15.125)
Reading Rainbow: The Best Unicorn Ever (infinity)

입력 예 2

Matthew
Mark
Luke
John
Revelations

출력 예 2 (추론을 나타 내기 위해 괄호 안에 "점수"가있는 경우 인쇄 할 필요가 없습니다)

Mark (12.375)
John (13)
Revelations (13.545454...)
Luke (13.75)
Matthew (~13.786)

입력 예 3

42
9 Kings
1:8
7th

출력 예 3 (추론을 나타 내기 위해 괄호 안에 "점수"가있는 경우 인쇄 할 필요가 없습니다)

42 (-42)
1:8 (-9.3333...)
9 Kings (~0.36)
7th (2.3333...)

다른 제한

  • 이것은 사서의 끊임없는 시선에서 프로그램을 비밀로 유지해야하기 때문에 코드 골프입니다. 프로그램이 작을수록 숨기는 것이 더 쉽습니다.
  • 표준 허점 제한이 적용됩니다
  • PPCG에 모든 시간을 투자하여 사서가 당신을 느슨하게 잡지 못하게하십시오.

만약 두 권의 책이 정확히 같은 점수라면? 즉, 나는 무지개와 루비 레일을 읽을 수 있습니다
— Kishan Kumar

@KishanKumar이 특정 예에서, "목록의 끝에 무작위로 배열 된"둘 다 double-R이기 때문입니다. 다시 말해, 선택하십시오. 일반적으로 두 단어의 점수가 같으면 서로 관련하여 어떤 순서로나 나타날 수 있습니다. 명확히하기 위해 글 머리 기호를 추가하겠습니다.
— AdmBorkBork

7
시스템의 약어 이름을 갖도록 A 단어가 필요합니다. D : 나는 미친 사서의 놀라운 정렬 시스템 추천
— Geobits

3
@Geobits CLASS가 있습니까?
— AdmBorkBork

숫자는 단지 십진수입니까? 여러 개가 있으면 모두 빼기합니까?
— Paŭlo Ebermann

답변:


5

APL (132)

{⎕ML←3⋄⍵[⍋{2='R'+.=↑¨⍵⊂⍨⍵≠' ':!99⋄↑(+/⍎¨'0',⍵⊂⍨⍵∊⎕D)-⍨((+/∊1.5 1×(⍳×∊⍨)∘⍵¨G)-+/⍵∊(⎕UCS 32+⍳94)~'`',⎕D,∊G←(⊂⎕A),⊂⎕UCS 96+⍳26)÷⍴⍵}¨⍵]}

다른 모든 사람들이 같은 일을하고 있기 때문에 제목 배열을 가져 와서 정렬 된 함수를 반환합니다.

      titles
┌─────────────┬──────────────────────────────────────┬────┬────────────────┬───────┬────┬────┬────┬───────────┬──┬───────┬───┬───┐
│War and Peace│Reading Rainbow: The Best Unicorn Ever│Maus│Home for a Bunny│Matthew│Mark│Luke│John│Revelations│42│9 Kings│1:8│7th│
└─────────────┴──────────────────────────────────────┴────┴────────────────┴───────┴────┴────┴────┴───────────┴──┴───────┴───┴───┘

      {⎕ML←3⋄⍵[⍋{2='R'+.=↑¨⍵⊂⍨⍵≠' ':!99⋄↑(+/⍎¨'0',⍵⊂⍨⍵∊⎕D)-⍨((+/∊1.5 1×(⍳×∊⍨)∘⍵¨G)-+/⍵∊(⎕UCS 32+⍳94)~'`',⎕D,∊G←(⊂⎕A),⊂⎕UCS 96+⍳26)÷⍴⍵}¨⍵]}titles
┌──┬───┬───────┬───┬─────────────┬────────────────┬────┬────┬───────────┬────┬───────┬────┬──────────────────────────────────────┐
│42│1:8│9 Kings│7th│War and Peace│Home for a Bunny│Mark│John│Revelations│Luke│Matthew│Maus│Reading Rainbow: The Best Unicorn Ever│
└──┴───┴───────┴───┴─────────────┴────────────────┴────┴────┴───────────┴────┴───────┴────┴──────────────────────────────────────┘

설명:

  • ⎕ML←3: 설정 ⎕ML에 3(에 대한 ⊂)
  • ⍵[⍋{... }¨⍵]: 내부 함수에서 반환 된 값을 기준으로 입력을 정렬
    • ↑¨⍵⊂⍨⍵≠' ': 각 단어의 첫 문자를 가져옵니다
    • 2='R'+.=:이 중 두 가지가 있는지 확인하십시오 'R'.
    • :!99: 그렇다면 99를 반환하십시오! (≈ 9.3 × 10 155 ). 이것은 매우 무한대 아니지만, 그것은 할 것입니다 : 제목이 38 배 길이 (ZZZZ ...)보다, 그래서 한없이 하나의 제목으로 × 10 2에 대한보다 큰 더 점수를 가질 수 없어 130 요타 바이트, 그것은 이것들이 끝날 것이라고 보장합니다.
    • ⋄: 그렇지 않으면 :
    • (... )÷⍴⍵: 점수를 ⍵계산 후 길이로 나눕니다 .
      • G←(⊂⎕A),(⎕UCS 96+⍳26): G대문자와 소문자로 저장
      • (⎕UCS 32+⍳94)~'`',⎕D,∊G: '`'점을 빼는 문자 인 문자, 숫자, 공백 및을 제외한 인쇄 가능한 ASCII 문자 . ( G나중에 사용 되기 때문에 모두 작성하는 것보다 짧습니다 .)
      • +/⍵∊:이 문자의 수를 세어보세요 ⍵
      • -: 이것을 빼기 :
      • +/∊1.5 1×(⍳×∊⍨)∘⍵¨G: 대문자의 점수의 1.5 배와 소문자의 점수의 합은 1 배입니다.
    • -⍨: 이후에 숫자의 총계를 빼십시오 ⍵.
      • ⍵⊂⍨⍵∊⎕D:에서 숫자 그룹을 찾습니다 ⍵
      • '0',: add '0', 목록이 비어 있지 않도록
      • ⍎¨: 각 문자열을 평가
      • +/: 합계를 찾으십시오

대신 !99사용할 수 있습니다⌊/⍬
— Adám

1
나는 APL에서 긴 코드를 보는 것을 좋아합니다. 세상이 나보다 훨씬 크다고 느끼게하고 상징도 좋아합니다.
— Conor O'Brien

2

루아 5.3, 366 364 바이트

r={}for i,s in ipairs(arg)do n=0 s:gsub("%l",function(a)n=n+(a:byte()-96)end):gsub("%u",function(a)n=n+(a:byte()-64)*1.5 end):gsub("%p",function(a)n=n-1 end):gsub("^R?.- R.- ?R?",function()n=math.huge end)m=n/utf8.len(s)s:gsub("%d+",function(a)m=m-a end)table.insert(r,{s=s,n=m})end table.sort(r,function(a,b)return a.n<b.n end)for i,v in ipairs(r)do print(v.s)end

이 코드는 유니 코드 문자를 처리해야하기 때문에 Lua 5.3에서만 작동합니다. 유니 코드에 신경 쓰지 않으면 "utf8"을 "string"으로 바꾸면 Lua 5.2 또는 5.1에서 잘 작동합니다.

명령 줄 인수에서 입력을 받으므로 명령 줄에서 실행 하거나이 코드를 내 대답 위에 놓으십시오.

arg = {"Title 1", "Title 2", "Title 3"}

내 컴퓨터에 루아 5.3이없는,하지만 난 스왑에 대한 귀하의 제안을 따라 utf8와 string에 Ideone 더 출력 없어.
— AdmBorkBork

@TimmyD 내 편집 내용보기
— Trebuchette

좋은. 육수. 그리고 (arg)얼굴에 나를 쳐다보고 거기 앉아있다. 이 질문은 분명히 내 두뇌를 떨어 뜨렸다. +1하십시오.
— AdmBorkBork

MoonScript에서 pastebin.com/wr4qVs5h 는 266 바이트 입니다.
— kirbyfan64sos

2

Mathematica, 253216 바이트 (214 자)

r=RegularExpression;c=ToCharacterCode;f=SortBy[Tr@Flatten@Reap[StringCases[#,
{r@"(\\bR.*)+"->∞,r@"\\d+":>0Sow@-FromDigits@"$0",r@"[a-z]":>c@"$0"-96,
r@"[A-Z]":>1.5c@"$0"-96,r@"[!-/:-@[-_{-~]"->-1}]/StringLength@#]&]

다음과 같이 함수를 호출하십시오 f[{"42", "9 Kings", "1:8", "7th"}]. 정렬 된 입력 목록을 반환합니다.

간신히 만들었습니다! Mathematica 의 패턴 일치는 문자열이 관련 될 때 간결하지 않으며, 나는 그 긴 이름에 의해 죽습니다. 추가 2 바이트는 Infinity유니 코드 문자를 위한 것 입니다.

(표준 허점을 무시한 경우 알려주세요.)

최신 정보

edc65의 답변을 조금 더 자세히 살펴보면 OP가 문자열 목록을 정렬하는 함수를 허용하는 것처럼 보입니다. 이를 염두에두고 카레 형식 SortBy( Mathematica 는 "연산자 형식"이라고 함)을 사용할 수 있습니다. 하나의 인수 (목록 요소에 적용되는 함수로 순서를 결정)는 하나의 인수를 취하는 함수처럼 동작하여 정렬 된 입력 형식을 반환합니다. 즉, SortBy[list, f]와 같습니다 (SortBy[f])[list].

언 골프

Function[{titles},
  SortBy[titles, Function[{str}, (* sort by function value *)
    Total[Flatten[Reap[ (* total up all the parts *)
      StringCases[str, {
        RegularExpression["(\\bR.*){2}"] -> Infinity
          (* matches R at the start of a word twice, adds infinity to the total *),
        RegularExpression["\\d+"] :> 0 * Sow[-FromDigits["$0"]]
          (* matches a number, Sows it for Reap to collect, then multiplies by zero
                                                          to not affect the average *),
        RegularExpression["[a-z]"] :> ToCharacterCode["$0"] - 96
          (* matches a lowercase letter and returns its value *),
        RegularExpression["[A-Z]"] :> 1.5 ToCharacterCode["$0"] - 96
          (* matches an uppercase letter and returns 1.5 its value *),
        RegularExpression["[!-/:-@[-_{-~]"] -> -1
          (* matches a 'grandiose' symbol and returns -1 *)
      }] / StringLength[#] (* averages character values *)
    ]]]
  ]]
]

1
좋은 대답, 그리고 당신은 계산에 문자 그대로 "무한대"를 사용하기위한 인터넷 쿠키를 얻습니다 ;-).
— AdmBorkBork

@TimmyD 상징적 수학 처리의 아름다움 =)
— 2012rcampion

아마 당신은 214 문자, 216 바이트를 의미합니다. 잘 했어요, 경쟁하려고했지만 방법은 없습니다
— edc65

2

자바 스크립트 (ES6) 210 218 251

배열 인수가있는 함수로 정렬 된 상태로 반환됩니다.

f=L=>(S=s=>([...s].map(c=>t-=(a=s.charCodeAt(l++))>32&a<48|a>57&a<65|a>90&a<96|a>122&a<127?1:a>64&a<123?96-(a<96?a*1.5:a):0,l=t=0),s.split(/\D/).map(n=>t-=n,t/=l),t/!s.split(/\bR/)[2]),L.sort((a,b)=>S(a)-S(b)))

//TEST

test1=['War and Peace','Reading Rainbow: The Best Unicorn Ever','Maus','Home for a Bunny']
test2=['Matthew','Mark','Luke','John','Revelations']
test3=['42','9 Kings','1:8','7th']

;O.innerHTML=f(test1)+'\n\n'+f(test2)+'\n\n'+f(test3);

// The comparing function used to sort, more readable

Sort=s=>(
  t = 0, // running total
  l = 0, // to calc the string length avoiding the '.length' property
  [...s].map(c=>{
    a=s.charCodeAt(l++);
    t-=a>32&a<48|a>57&a<65|a>90&a<96|a>122&a<127
      ? 1 // symbols (ASCII char except space, alphanumeric and backtick)
      : a>64&a<123 
        ? 96-(a<96?a*1.5:a) // alphabetic both upcase and lowcase, and backtick
        // lowcase: 96-a, upcase (64-a)*1.5=>96-a*1.5, backtick is 96 and 96-96 == 0
        : 0 // else space, non ASCII, and numeric : 0
  }),
  t = t/l, // average
  s.split(/\D/).map(n=>t-=n), // sub number values
  f = s.split(/\bR/)[2], // split at words starting with R, if less then 2 f is undefined
  t/!f // dividing by not f I can get the infinity I need
)
<pre id=O></pre>


잘 했어요 이 답변을 읽는 다른 사람을 참조하기 위해 Firefox의 콘솔 로 변경 O.innerHTML해야 this.InnerHTML했습니다.
— AdmBorkBork

1

C #을 352 349 바이트

linq의 마법으로 인해 :

class A{static void Main(string[]a){foreach(var x in a.OrderBy(b=>{var s="0";int j=0;return Regex.Split(b,@"[^\w]+").Count(l=>l[0]=='R')==2?(1/0d):b.Aggregate(0d,(d,e)=>{if(e>47&e<58){s+=e;return d;}d+=(e>64&e<91)?(e-64)*1.5:(e>96&e<123)?e-96:e>32&e<127&e!=96?-1:0;j+=int.Parse(s);s="0";return d;})/b.Length-j-int.Parse(s);}))Console.WriteLine(x);}}

역 따옴표가 문장 부호 목록에 포함되면 6 바이트를 더 절약 할 수 있습니다.

class A
{
    static void Main(string[] a)
    {
        foreach (var x in a.OrderBy(b =>
            {
                var s = "0";
                int j = 0;
                return Regex.Split(b, @"[^\w]+").Count(l => l[0] == 'R') == 2
                    ? (1 / 0d)
                        : b.Aggregate(0d, (d, e) =>
                        {
                            if (e > 47 & e < 58) { s += e; return d; }
                            d += (e > 64 & e < 91) ? (e - 64) * 1.5 : (e > 96 & e < 123) ? e - 96 : e > 32 & e < 127 & e != 96 ? -1 : 0;
                            j += int.Parse(s);
                            s = "0";
                            return d;
                        }) / b.Length - j - int.Parse(s);
            }))
            Console.WriteLine(x);
    }

}

1

이동, 755 바이트

package main
import("os"
"fmt"
"math"
"bufio"
"regexp"
"sort"
"strconv")
type F float64
type T []F
func(t T)Swap(i,j int){t[i],t[j],S[i],S[j]=t[j],t[i],S[j],S[i]}
func(t T)Len()int{return len(t)}
func(t T)Less(i,j int)bool{return t[i]<t[j]}
var S []string
func main(){var t T
for{b:=bufio.NewReader(os.Stdin)
w,_,_:=b.ReadLine()
if len(w)==0{break}
u:=string(w)
var v F
for _,c:=range u{if 96<c&&c<123{v+=F(c)-F(96)}else
if 64<c&&c<91{v+=(F(c)-64)*1.5}else
if (48>c&&c>32)||(c>57&&c<127){v-=1}}
a:=v/F(len(w))
r,_:=regexp.Compile("[0-9]+")
n:=r.FindAllString(string(w),-1)
for _,x:=range n{y,_:=strconv.Atoi(x);a-=F(y)}
if m,_:=regexp.Match("((^| )R.*){2}",w);m{a=F(math.Inf(1))}
S=append(S,u)
t=append(t,a)}
sort.Sort(t)
for _,o:=range S{fmt.Println(o)}}

형식화 된 버전 :

package main

import (
    "bufio"
    "fmt"
    "math"
    "os"
    "regexp"
    "sort"
    "strconv"
)

type F float64
type T []F

func (t T) Swap(i, j int)      { t[i], t[j], S[i], S[j] = t[j], t[i], S[j], S[i] }
func (t T) Len() int           { return len(t) }
func (t T) Less(i, j int) bool { return t[i] < t[j] }

var S []string

func main() {
    var t T
    for {
        b := bufio.NewReader(os.Stdin)
        w, _, _ := b.ReadLine()
        if len(w) == 0 {
            break
        }
        u := string(w)
        var v F
        for _, c := range u {
            if 96 < c && c < 123 {
                v += F(c) - F(96)
            } else if 64 < c && c < 91 {
                v += (F(c) - 64) * 1.5
            } else if (48 > c && c > 32) || (c > 57 && c < 127) {
                v -= 1
            }
        }
        a := v / F(len(w))
        r, _ := regexp.Compile("[0-9]+")
        n := r.FindAllString(string(w), -1)
        for _, x := range n {
            y, _ := strconv.Atoi(x)
            a -= F(y)
        }
        if m, _ := regexp.Match("((^| )R.*){2}", w); m {
            a = F(math.Inf(1))
        }
        S = append(S, u)
        t = append(t, a)
    }
    sort.Sort(t)
    for _, o := range S {
        fmt.Println(o)
    }
}

사용자 정의 정렬 인터페이스를 구현하면 예상보다 오래 걸렸습니다. 빈 줄이 입력 될 때까지 프로그램은 STDIN에서 읽습니다.


1

PHP, 362 367 바이트

<?for(;$w=fgets(STDIN);$S[]=$w){for($l=$i=mb_strlen($w);$i--;){$c=array_sum(unpack("C*",mb_substr($w,$i,1)));96<$c&&$c<123 and $v+=$c-96 or 64<$c&&$c<91 and $v+=1.5*$c-96 or 48<$c&&$c>32||$c>57&&$c<127 and $v-=1;}$v/=$l;preg_match_all("/\d+/",$w,$m);$v-=array_sum($m[0]);preg_match("/((^| )R.*){2}/",$w)&&$v=INF;$t[]=$v;}array_multisort($t,$S);echo join("
",$S);

형식화 된 버전 :

<?php
for (; $w = fgets(STDIN); $S[] = $w) {
    for ($l = $i = mb_strlen($w); $i--;) {
        $c = array_sum(unpack("C*", mb_substr($w, $i, 1)));
        96 < $c && $c < 123 and $v += $c - 96
        or 64 < $c && $c < 91 and $v += 1.5 * $c - 96
        or 48 < $c && $c > 32 || $c > 57 && $c < 127 and $v -= 1;
    }
    $v /= $l;
    preg_match_all("/\d+/", $w, $m);
    $v -= array_sum($m[0]);
    preg_match("/((^| )R.*){2}/", $w) && $v = INF;
    $t[] = $v;
}
array_multisort($t, $S);
echo join("
", $S); 

재미있는 라인 :

$c = array_sum(unpack("C*", mb_substr($w, $i, 1)));

단일 UTF-8 문자를 바이트 값으로 변환하고 합산하여 ASCII 문자의 실제 값과 멀티 바이트 문자의 경우 127보다 큰 값을 얻습니다.

96 < $c && $c < 123 and $v += $c - 96
or 64 < $c && $c < 91 and $v += 1.5 * $c - 96
or 48 < $c && $c > 32 || $c > 57 && $c < 127 and $v -= 1;

차종은 낮은 연산자 우선 순위의 사용 and및 or없이 하나의 문에서 문자 값을 할당합니다 if.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.