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


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: 설정 ⎕ML3(에 대한 )
  • ⍵[⍋{... }¨⍵]: 내부 함수에서 반환 된 값을 기준으로 입력을 정렬
    • ↑¨⍵⊂⍨⍵≠' ': 각 단어의 첫 문자를 가져옵니다
    • 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이없는,하지만 난 스왑에 대한 귀하의 제안을 따라 utf8stringIdeone 더 출력 없어.
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;

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


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