รูปแบบของ Golf String () ตรงกันข้าม


13

สลับวิธีการจัดรูปแบบ

Formatวิธีการของการเรียน String (หรือ equivallent เช่นsprintf) มีให้บริการในภาษามากที่สุด โดยทั่วไปจะใช้สตริง "รูปแบบ" ซึ่งอาจมีตัวยึดตำแหน่งที่มีการจัดรูปแบบพิเศษบางอย่างและจะแทรกค่าเป็นศูนย์หรือมากกว่านั้นแทนตัวยึดตำแหน่งเหล่านั้น

งานของคุณคือการใช้ฟังก์ชั่นผกผันในภาษาที่คุณเลือก

API

ชื่อวิธีที่ควรจะเป็นอย่างใดอย่างหนึ่งหรือformat1deformat

อินพุต : พารามิเตอร์ที่ 1 จะเป็นสตริง "รูปแบบ" เช่นเดียวกับในรูปแบบวิธีดั้งเดิม พารามิเตอร์ที่สองจะเป็นสตริงการแยกวิเคราะห์ (ดูตัวอย่างด้านล่าง) ไม่มีพารามิเตอร์อื่น ๆ ที่จำเป็นและไม่ได้รับอนุญาต

เอาท์พุท : อาร์เรย์ (หรือค่าที่เทียบเท่ากับภาษาที่คุณเลือก) ซึ่งแตกออกมาอย่างสอดคล้องกับตัวยึดตำแหน่งในรูปแบบ

ตัวยึดตำแหน่งมี{0}, {1}, {2}ฯลฯ

ในกรณีที่รูปแบบไม่ดีคุณอาจโยนข้อผิดพลาดหรือคืนสิ่งที่คุณต้องการ

ในกรณีที่อินพุตไม่ถูกต้องคุณอาจโยนข้อผิดพลาดหรือคืนสิ่งที่คุณต้องการ การป้อนข้อมูลที่ไม่ถูกต้องเป็นเช่นนั้นไม่สามารถสร้างขึ้นโดยใช้ String.Format '{0}{0}', 'AAB'สตริงรูปแบบเดียวกันตัวอย่างเช่น:

ตัวอย่าง

deformat('{0} {1}', 'hello world') => ['hello', 'world']
deformat('http{0}://', 'https://') => ['s']
deformat('http{0}://', 'http://') => [''] // array of one item which is an empty string
deformat('{0}{1}{0}', 'ABBA') => ['A', 'BB']

ความคลุมเครือ

ในกรณีที่มีความกำกวมคุณอาจส่งคืนคำตอบที่เหมาะสม ตัวอย่างเช่น:

deformat('{0} {1}', 'Edsger W. Dijkstra')
// both ['Edsger', 'W. Dijkstra'] and ['Edsger W.', 'Dijkstra'] are applicable.

บางกฎเพิ่มเติม

  • เพื่อให้ง่ายขึ้นคุณไม่จำเป็นต้องรองรับการฟอร์แมต คุณสามารถลืมทั้งหมดเกี่ยวกับศูนย์นำหน้าจุดทศนิยมหรือปัญหาการปัดเศษ เพียงสร้างค่าเป็นสตริง
  • ที่จะทำให้มันไม่น่ารำคาญนิพจน์ปกติไม่ได้รับอนุญาต
  • คุณไม่จำเป็นต้องดูแลวงเล็บปีกกาในอินพุต (เช่นพารามิเตอร์อินพุตที่ 2 จะไม่มี{s หรือ s ใด ๆ})

การชนะ

นี่คือ ! (ควรอ่านว่า "นี่คือสปาร์ตา!") ฟังก์ชั่นที่ถูกต้องซึ่งมีความยาวชนะสั้นที่สุด ช่องโหว่มาตรฐานเป็นสิ่งต้องห้าม


ในตัวอย่างจะdeformat('{0}{1}{0}', 'ABBA') => ['A', 'BB']เกิดอะไรขึ้นถ้าเราได้รับแทนdeformat('{0}{1}{0}', 'AAAA')?
xnor

@xnor - กว่าที่เรามีความคลุมเครือและแต่ละคนต่อไปจะเป็นเอาท์พุทที่ถูกต้อง: ['', 'AAAA'], ['A', 'AA'],['AA', '']
จาค็อบ

จะมีเอาท์พุทแล้วdeformat('{0}{1}{0}', 'ABBA') => ['', 'ABBA']? ถ้าเป็นเช่นนั้นจะมีวิธีแก้ปัญหาราคาถูกเว้นแต่ว่าทุกสตริงปรากฏอย่างน้อยสองครั้ง
xnor

โซลูชั่นราคาถูกของคุณจะทำงานด้วยdeformat('{0}_{1}_{0}', 'A_BB_A')หรือไม่
จาค็อบ

โอ้ฉันเข้าใจแล้วฉันลืมเกี่ยวกับตัวละครที่เกิดขึ้นจริงในผลลัพธ์ ฉันยังคงพยายามห่อหัวของฉันรอบ ๆ วิธียากนี้เป็น ให้ฉันดูว่าฉันสามารถทำอินสแตนซ์ที่ผิดปกติจริง ๆ
xnor

คำตอบ:


2

Haskell, 220 ตัวอักษร

import Data.Map;f""""=[empty]
f('{':b)d=[insert k m b|(k,('}':a))<-lex b,(m,c)<-[splitAt n d|n<-[0..length d]],b<-f a c,notMember k b||b!k==m]
f(x:b)(y:d)|x==y=f b d;f _ _=[];format1 x y=elems$mapKeys((0+).read)$f x y!!0

แตกถ้าคุณใช้การแทนหลายครั้งสำหรับรูปแบบเดียวกัน ( {1}vs {01}) - ไม่บังคับใช้ความเท่าเทียมกันโดยละทิ้งการแข่งขันสำหรับทั้งหมดยกเว้นการแสดงเพียงครั้งเดียวแทน

สามารถบันทึกอักขระได้ 19 ตัวโดยละเว้นmapKeys((0+).read)$หากการเรียงลำดับการจับคู่ที่เหมาะสมเหนือ 10 รูปแบบไม่สำคัญหรืออาจต้องใช้การขยายความยาวเท่ากันหรือหากการเรียงลำดับรูปแบบเป็นที่ยอมรับ ไม่ว่าในกรณีใดถ้ารูปแบบถูกตัดออกจากอาร์กิวเมนต์แรกมันจะถูกตัดออกจากผลลัพธ์เช่นกัน

การลบออก!!0จากตอนท้ายทำให้format1ส่งคืนรายการโซลูชันทั้งหมดไม่ใช่แค่โซลูชันแรก

ก่อนเล่นกอล์ฟ:

import Data.Map
import Control.Monad

cuts :: [a] -> [([a],[a])]
cuts a=[splitAt n a | n <- [0..length a]]

f :: String -> String -> [Map String String]
-- empty format + empty parsed = one interpretation with no binding
f "" "" = [empty]
-- template-start format + some matched = branch search
f ('{':xs) ys = do
    let [(key, '}':xr)] = lex xs
    (match, yr) <- cuts ys
    b <- f xr yr
    guard $ notMember key b || b!key == match
    return $ insert key match b
-- non-empty format + matching parsed = exact match
f (x:xs) (y:ys) | x == y = f xs ys
-- anything else = no interpretation
f _ _ = []

deformat :: String -> String -> [String]
deformat x y = elems $ mapKeys ((0+).read) $ head $ f x y

ที่นั่น (0+)? ไม่ใช่แค่เขียนอ่านให้สั้นลง?
ภูมิใจ haskeller

@proudhaskeller readทำให้คุณมีความรู้สึกที่ไม่ชัดเจน Haskell ไม่รู้ประเภทที่สามารถสั่งให้อ่านคีย์ได้ +0บังคับให้ตัวเลขซึ่ง Haskell สามารถเลือกได้ตามต้องการแล้วจึงไปหาจำนวนเต็ม
John Dvorak

2

Ruby, 312 ตัวอักษร

class String
def-@
self[0,1].tap{self[0,1]=''}end
end
def format1 f,s,r=[]
loop{if'{'==c=-f
n,f=f.split('}',2)
[*1..s.length,0].each{|i|next if'{'!=f[0]&&s[i]!=f[0]
if u=format1((g=f.gsub("{#{n}}",q=s[0,i])).dup,s[i..-1],r.dup)
r,s,f=u,s[i..-1],g
r[n.to_i]=q
break
end}else
c!=-s&&return
end
""==c&&break}
r
end

สามารถบันทึกอักขระได้ 5 ตัวโดยเลือกการจับคู่ที่ไม่มีความยาวเป็นศูนย์ทำให้เกิดABBAโซลูชัน['', 'ABBA']แทนที่จะเป็นโซลูชันที่ต้องการ ฉันเลือกที่จะตีความตัวอย่างเป็นส่วนหนึ่งของข้อกำหนด


1

Python, 208 ตัวอักษรแม้ว่าจะไม่สมบูรณ์

def format1(i,o):
 i+=" ";o+=" ";x=y=0;s=[]
 while x<len(i):
  if i[x]=="{":
   try:y+=len(s[int(i[x+1])])
   except:
    s+=[""]
    while o[y]!=i[x+3]:s[int(i[x+1])]+=o[y];y+=1
   x+=3
  x+=1;y+=1
 return s

ฟังก์ชั่นกวาดทั้งสองสตริงพร้อมกันจนกว่าจะพบวงเล็บเปิดในสตริงป้อนข้อมูลที่บ่งบอกถึงตัวยึด

จากนั้นจะถือว่าตัวยึดได้ถูกขยายออกไปแล้วและพยายามที่จะพัฒนาดัชนีของสตริงเอาต์พุตให้ผ่านโดยดูที่รายการค่าที่พบ

หากยังไม่ได้ขยายจะเพิ่มรายการใหม่ลงในรายการค่าและเริ่มเพิ่มอักขระจากสตริงออกจนกว่าจะถึงอักขระหลังจากตัวยึดตำแหน่งในสตริงอินพุต

เมื่อถึงจุดสิ้นสุดของสตริงอินพุตมันจะส่งคืนค่าที่พบจนถึงปัจจุบัน


มันทำงานได้ดีสำหรับอินพุตที่เรียบง่าย แต่มีปัญหาหลายประการ:

  • ต้องการตัวคั่นที่รู้จักหลังจากตัวยึดตำแหน่งแต่ละตัวในอินพุตดังนั้นจึงไม่สามารถทำงานร่วมกับตัวยึดตำแหน่งที่อยู่ติดกันเช่น "{0} {1}" นี่คือเหตุผลที่ฉันต้องการผนวกอักขระพิเศษให้กับสตริงทั้งสอง

  • จะถือว่าอินสแตนซ์แรกของแต่ละตัวยึดตำแหน่งอยู่ในลำดับเช่น "{ 0 } { 1 } {1} {0} { 2 }"

  • ใช้งานได้กับตัวแทน 10 รายแรกเท่านั้นเนื่องจากถือว่ามีทั้งหมด 3 ตัวอักษร

  • มันไม่ได้จัดการกับกรณีที่คลุมเครือเลย :(


1

รหัส C ++ 11, 386 ตัวอักษร

#include <string>
#include <map>
using namespace std;using _=map<int,string>;using X=const char;_ format1(X*p,X*s,_ k=_()){_ r;while(*p!='{'){if(!*p||!*s){return*p==*s?k:r;}if(*p++!=*s++)return r;}int v=0;while(*++p!='}'){v=v*10+(*p-48);}p++;if(k.find(v)!=k.end()){return format1((k[v]+p).c_str(),s,k);}while((r=format1(p,s,k)).empty()){k[v]+=*s++;if(!*s){return*p==*s?k:r;}}return r;}

ฟังก์ชั่น format1 มี 2 สตริงเป็นอินพุต (const char *) และส่งคืน hashmap ที่มีจำนวนเต็มคีย์ (รูปแบบ) และค่าเป็นสตริงที่ระบุ หากไม่พบสิ่งใดหรือข้อผิดพลาดใด ๆ จะมีการส่งคืนค่าแฮชแมปที่ว่างเปล่า

การใช้งาน:

for (auto v : format1("{1} {2}", "one two")){
    cout << v.first << "=" << v.second << endl;
}

เอาท์พุท:

1=one
2=two

ตัวอย่างที่ 2:

auto v = format1("{1} {2}", "one two");
cout << v[1] << " and " << v[2] << endl;

เอาท์พุท:

one and two

รูปแบบอยู่ในรูปแบบทศนิยมการป้อนข้อมูลที่ใหญ่กว่าMAXINTจะล้น แต่ก็ยังใช้งานได้

แม้ว่าจะมีวิธีแก้ปัญหาน้อยกว่าในภาษาการเขียนโปรแกรมอื่น ๆ นี่คือ C ++ ที่เล็กที่สุด - แต่! :)

นี่คือรหัสก่อนเล่นกอล์ฟ:

#include <string>
#include <map>
using namespace std;

using res = map<int,string>;

res format1(const char* p, const char* s, res k=res()){
    res r; // intermediate result, empty until the end
    // match until first '{'
    while (*p != '{'){
        if (!*p || !*s){
            // exit case
            return ((*p == *s) ? k : r); // == 0
        }
        if (*p++ != *s++)
               return r;
    }

    // *p == '{'
    int v = 0;
    while(*++p != '}'){
        v = v*10 + (*p - '0');
    }
    p++; // advance past '}'

    // match back-references
    if (k.find(v) != k.end()){
       return format1((k[v]+p).c_str(), s, k);
    }

    // recursive search
    while ( (r=format1(p, s, k)).empty() ){
        k[v] += *s++;
        if (!*s){
            return *p == *s ? k : r;
        }
    }
    return r;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.