Golf String'in biçimi () ters


13

Format yöntemini ters çevirin.

FormatString sınıfının (veya equivallent gibi bir yöntem sprintf) çoğu dilde mevcuttur. Temel olarak, fazladan biçimlendirmeye sahip yer tutucular içerebilen ve bu yer tutucular yerine sıfır veya daha fazla değer eklenebilecek bir "Biçim" dizesi alır.

Göreviniz, ters işlevi tercih ettiğiniz dilde uygulamaktır.

API

Yöntem adı format1veya olmalıdır deformat.

Girdi : 1. parametre tıpkı orijinal biçim yönteminde olduğu gibi "Biçim" dizesi olacaktır. 2. parametre ayrıştırılmış dize olacaktır (aşağıdaki örneklere bakın). Başka hiçbir parametreye gerek yoktur.

Çıktı : biçimdeki yer tutucularla ilgili olarak çıkarılan değer dizisi (veya seçtiğiniz dilin eşdeğeri).

Tutuculardır {0}, {1}, {2}vb

Kötü biçim durumunda bir hata atabilir veya istediğinizi geri gönderebilirsiniz.

Geçersiz giriş durumunda bir hata atabilir veya istediğinizi geri gönderebilirsiniz. Geçersiz giriş, örneğin, aynı dizgi formatı kullanılarak String.Format tarafından oluşturulan edilemez şekildedir: '{0}{0}', 'AAB'.

Örnekler

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']

belirsizlik

Belirsizlik durumunda, uygun bir cevap verebilirsiniz. Örneğin:

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

Bazı Kurallar

  • Bunu kolaylaştırmak için biçimlendirmeyi desteklemeye gerek yoktur. Baştaki sıfırlar, ondalık nokta veya yuvarlama sorunları hakkında her şeyi unutabilirsiniz. Değerleri dize olarak oluşturmanız yeterlidir.
  • Önemsiz kılmak için Düzenli İfadelere izin verilmez .
  • Girişteki kıvırcık parantezlere dikkat etmeniz gerekmez (örn. 2. giriş parametresi herhangi bir {s veya }s içermez ).

Kazanan

Bu ! ("Bu Sparta!" olarak okunmalıdır) en kısa uzunlukta doğru fonksiyon kazanır. Standart boşluklar yasaktır.


Örnekte deformat('{0}{1}{0}', 'ABBA') => ['A', 'BB'], bize bunun yerine verilseydik deformat('{0}{1}{0}', 'AAAA')?
xnor

@xnor - Elimizde bir belirsizlik var ve aşağıdakilerden her biri geçerli bir çıkış olacağından daha: ['', 'AAAA'], ['A', 'AA'],['AA', '']
Jacob

Bu durumda biri çıktı alabilir deformat('{0}{1}{0}', 'ABBA') => ['', 'ABBA']mi? Öyleyse, her dize en az iki kez görünmedikçe ucuz bir çözüm vardır.
xnor

ucuz çözümünüz de işe yarayacak deformat('{0}_{1}_{0}', 'A_BB_A')mı?
Jacob

Anlıyorum, sonuçlarda gerçek karakterleri unutmuştum. Hala kafamı ne kadar algoritmik olarak zorlaştırmaya çalışıyorum. Bakalım gerçekten sapkın bir örnek oluşturabilir miyim.
xnor

Yanıtlar:


2

Haskell, 220 karakter

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

Aynı model ( {1}vs {01}) için birden çok gösterim kullanırsanız , eşitliklerini zorunlu kılmaz ve bunun yerine bir gösterim hariç tümü için eşleşmeleri atar.

10 kalıbın mapKeys((0+).read)$üzerindeki eşleşmelerin doğru sıralanması önemli değilse veya aynı uzunlukta dolgu gerekliyse veya kalıpların dize sıralaması kabul edilebilirse, 19 karakter atlanabilir . Her durumda, bir model ilk argümandan çıkarılırsa, sonuçtan da çıkarılır.

Sondan çıkarmak !!0, format1sadece ilk çözümden ziyade tüm çözümlerin listesini döndürür.

golf oynamadan önce:

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

orada (0+) var mı? sadece yazmak daha kısa değil mi?
gururlu haskeller

@proudhaskeller readbelirsiz bir tipte sizi bırakır. Haskell tuşları okumak için ne tür bir yazı tipini bilmiyor. +0Haskell'in zaten keyfi bir seçim yapabildiği ve tamsayılar için geçerli olduğu bir sayı zorlar.
John Dvorak

2

Ruby, 312 karakter

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 karakter, sıfır uzunluklu maçları tercih yaparak kaydedilmiş olabilir ABBAçözüm ['', 'ABBA']yerine Sorunun tercih çözümden çok,. Örnekleri şartnamenin ima edilen bir parçası olarak yorumlamayı seçtim.


1

Python, 208 karakter, eksik de olsa.

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

İşlev, giriş dizesinde bir yer tutucu belirten bir açılış ayracı bulana kadar her iki dizeyi aynı anda süpürür.

Ardından, yer tutucunun zaten genişletilmiş olduğunu varsayar ve şimdiye kadar bulunan değerler listesine bakarak çıkış dizesinin dizinini geçmeye çalışır.

Genişletilmemişse, değerler listesine yeni bir giriş ekler ve giriş dizesindeki yer tutucunun arkasındaki karaktere ulaşıncaya kadar çıkış dizesinden karakterler eklemeye başlar.

Giriş dizesinin sonuna geldiğinde, şimdiye kadar bulunan değerleri döndürür.


Basit girdiler için iyi çalışır, ancak bir takım sorunları vardır:

  • Girdideki her bir yer tutucudan sonra bilinen bir sınırlayıcı gerektirir, bu nedenle hemen yanındaki yer tutucularla çalışmaz, yani "{0} {1}". Bu yüzden her iki dizeye de bir boşluk karakteri eklemem gerekiyordu.

  • Her bir yer tutucunun ilk örneklerinin sıralı olduğunu varsayar, örneğin "{ 0 } { 1 } {1} {0} { 2 }".

  • Sadece 3 karakter uzunluğunda olduğunu düşündüğü için sadece ilk 10 yer tutucu için çalışır.

  • Belirsiz vakaları hiç ele almıyor :(


1

C ++ 11 kodu, 386 karakter

#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 işlevi girdi (const char *) olarak 2 dizeye sahiptir ve tamsayı (desen) tuşlarına sahip bir hashmap döndürür ve değer, tanımlanan dizedir. Hiçbir şey bulunmazsa veya herhangi bir hata yoksa, boş bir hashmap döndürülür.

Kullanımı:

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

Çıktı:

1=one
2=two

Örnek 2:

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

Çıktı:

one and two

Desenler ondalık gösterime sahiptir, girişler MAXINTtaşacak olandan daha büyüktür , ancak yine de çalışır.

Diğer programlama dillerinde daha küçük çözümler olmasına rağmen, bu en küçük C ++ - henüz! :)

Golften önceki kod:

#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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.