Lecture
Problem A. BibTEX
Input file: bibtex.in
Output file: bibtex.out
Time limit: 1 second
Memory limit: 256 megabytes
BibTeX is a tool for formatting lists of references. The BibTeX tool is typically used together with the
LaTeX document preparation system. BibTeX uses a style-independent text-based file format for lists of
bibliography items such as articles, books, theses.
Bibliography based on book and
article references description.
Reference description starts with “@reference type” followed by
as “name =" value "”, separated by commas, followed by '}'.
Your program must support the following reference types:
• article - An article from a journal or magazine.
Required fields: author, title, journal, year
Optional fields: volume, number, pages
• book - A book with an explicit publisher.
Required fields: author, title, publisher, year
Optional fields: volume
The fields are formatted as follows:
Field Description
author Each author is formatted as “Name1 Name2 ... Surname”. There are
at least 1 and at most 10 names. If there are several authors, they are
separated by “and”. No author has name or surname equal to “and”.
The total length of the field does not exceed 200 characters. Names and
surnames contain letters
by a space.
title title of the source. A string of up to 200 characters containing letters
of the English alphabet, spaces, digits and punctuation.
journal, publisher Journal name or publisher name. A string of up to 200 characters containing
letters, spaces, digits and punctuation.
year Integer number from 1500 to 2008.
volume Integer number from 1 to 106.
number Integer number from 1 to 106.
pages Formatted as “from - to” or as “page”. “From”, “to” and “page” are
integers from 1 to 106, “from” <“to”.
Authors of each source are sorted by surname, then by first name, second name, etc. After that all
references are sorted by first author, then first author, first author, then first author second name,
etc, then author, surname, etc, (if the corresponding name doesn’t exist, empty string is used
instead) then by title. (Except books)
that can have several volumes, such references are sorted by the volume).
Each article reference is formatted as:
“Authors Title // Journal [, Volume] [(Number)] - year [- pages]”.
Page 1 of 12
Andrew Stankevich Contest 30
Petrozavodsk, Thursday, February 7, 2008
Here “[...]” means optional part. Authors are separated by comma. Each author is formatted as
“Surname I1. I2. ... ”where I1, I2, etc are the author’s initials (
name). Pages are formatted either as “p. page ”if there is only one page, or“ pp. from - to ”
if there are many.
Each book reference is formatted as:
“Authors Title [, Vol. Volume] - Publisher, Year ”.
All references are numbered from 1 and preceded by their number in square brackets.
See example for further reference.
Input
BibTeX reference list containing up to 100 references. All entries in the input file are
case sensitive. All elements of the input file are line space and / or line feed.
Output
Output the bibliography in the required format.
Example
bibtex.in
@book
{
author = "Donald Ervin Knuth",
title = "The Art of Computer Programming",
volume = "1",
publisher = "Addison-Wesley Professional",
year = "1997"
}
@book
{
author = "Donald Ervin Knuth",
title = "The Art of Computer Programming",
volume = "2",
publisher = "Addison-Wesley Professional",
year = "1997"
}
@article
{
author = "Robert Endre Tarjan and Andrew Goldberg",
title = "A new approach to the maximum flow problem",
journal = "Journal ACM",
volume = "35",
year = "1988",
pages = "921--940"
}
bibtex.out
[1] Goldberg A., Tarjan RE A new approach to the maximum flow problem // Journal ACM, 35 - 1988 - pp. 921--940
[2] Knuth DE The Art of Computer Programming, Vol. 1 - Addison-Wesley Professional, 1997
[3] Knuth DE The Art of Computer Programming, Vol. 2 - Addison-Wesley Professional, 1997
#include <cstdio> | |
#include <algorithm> | |
#include <cstring> | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include <cctype> | |
#include <sstream> | |
#define SIZE (x) ((int) (x) .size ()) | |
#define ALL (x) (x) .begin (), (x) .end () | |
#define Vector std :: vector | |
#define String std :: string | |
const int MAX_NAME = 10; | |
struct Author {// {{{ | |
String surname, name [MAX_NAME]; | |
void clear () { | |
surname = ""; | |
for (int i = 0; i <MAX_NAME; i ++) { | |
name [i] = ""; | |
} | |
} | |
Author () { | |
clear (); | |
} | |
bool operator! = (const Author & o) const { | |
if (surname! = o.surname) { | |
return true; | |
} | |
for (int i = 0; i <MAX_NAME; i ++) { | |
if (name [i]! = o.name [i]) { | |
return true; | |
} | |
} | |
return false; | |
} | |
bool operator <(const Author & o) const { | |
if (surname! = o.surname) { | |
return surname <o.surname; | |
} | |
for (int i = 0; i <MAX_NAME; i ++) { | |
if (name [i]! = o.name [i]) { | |
return name [i] <o.name [i]; | |
} | |
} | |
return false; | |
} | |
void print () { | |
printf ("% s", surname.c_str ()); | |
for (int i = 0; i <MAX_NAME && SIZE (name [i])> 0; i ++) { | |
putchar (''); | |
putchar (toupper (name [i] [0])); | |
putchar ('.'); | |
} | |
} | |
}; //}}} | |
struct Reference {// {{{ | |
bool isarticle; | |
Vector <Author> authors; | |
String title, journal, publisher; | |
int year, volume, number, page [2]; | |
void clear () { | |
isarticle = false; | |
authors.clear (); | |
title = journal = publisher = ""; | |
year = volume = number = page [0] = page [1] = -1; | |
} | |
Reference () { | |
clear (); | |
} | |
void normalize () { | |
std :: sort (ALL (authors)); | |
} | |
bool operator <(const Reference & o) const { | |
int max = std :: max (SIZE (authors), SIZE (o.authors)); | |
for (int i = 0; i <max; i ++) { | |
if (i <SIZE (authors) && i <SIZE (o.authors)) { | |
if (authors [i]! = o.authors [i]) { | |
return authors [i] <o.authors [i]; | |
} | |
} else { | |
return i> = SIZE (authors); | |
} | |
} | |
if (title! = o.title) { | |
return title <o.title; | |
} | |
return volume <o.volume; | |
} | |
void authors_title_print () { | |
for (int i = 0; i <SIZE (authors); i ++) { | |
putchar (''); | |
authors [i] .print (); | |
putchar (i <SIZE (authors) - 1? ',': ''); | |
} | |
printf ("% s", title.c_str ()); | |
} | |
void article_print (int id) { | |
printf ("[% d]", id); | |
authors_title_print (); | |
printf ("//"); | |
printf ("% s", journal.c_str ()); | |
if (volume! = -1) { | |
printf (",% d", volume); | |
} | |
if (number! = -1) { | |
printf ("(% d)", number); | |
} | |
printf ("-% d", year); | |
if (page [0]! = -1) { | |
if (page [0] == page [1]) { | |
printf ("- p.% d", page [0]); | |
} else { | |
printf ("- pp.% d -% d", page [0], page [1]); | |
} | |
} | |
puts (""); | |
} | |
void book_print (int id) { | |
printf ("[% d]", id); | |
authors_title_print (); | |
if (volume! = -1) { | |
printf (", Vol.% d", volume); | |
} | |
printf ("-% s,% d \ n", publisher.c_str (), year); | |
} | |
}; //}}} | |
Vector <Reference> vector; | |
int n; | |
Author aut; | |
Reference ref; | |
char a [int (1e7) + 10]; | |
char buf [int (1e6) + 10]; | |
int next_space (int p) { | |
for (p ++; p <n && a [p]! = '' && a [p]! = '{'; p ++); | |
return p; | |
} | |
int next_char (int p) { | |
for (p ++; p <n && a [p] == ''; p ++); | |
return p; | |
} | |
int next_break (int p) { | |
for (p ++; p <n && a [p]! = '{' && a [p]! = '}' && a [p]! = '='; p ++); | |
if (a [p] == '=') { | |
for (; a [p]! = ','; p--); | |
} | |
return p; | |
} | |
int next_double (int p) { | |
for (p ++; p <n && a [p]! = '"'; p ++); | |
return p; | |
} | |
int to_number (const String & s) { | |
std :: istringstream sin (s); | |
int x; | |
sin >> x; | |
return x; | |
} | |
int main () { | |
n = 0; | |
while (gets (buf)) { | |
int m = strlen (buf); | |
for (int i = 0; i <m; i ++) { | |
a [n ++] = buf [i]; | |
} | |
} | |
a [n] = 0; | |
for (int i = 0, j; i <n; i ++) { | |
if (a [i]! = '@') { | |
continue; | |
} | |
ref.clear (); | |
j = next_space (i); | |
if (String (a + i, a + j) == String ("@ article")) { | |
ref.isarticle = true; | |
} else { | |
ref.isarticle = false; | |
} | |
i = next_break (i); | |
while (true) { | |
j = next_space (i = next_char (i)); | |
String token = String (a + i, a + j); | |
int s = next_double (j); | |
int t = next_break (s); | |
int pos = t; | |
s ++; | |
for (; a [t]! = '"'; t--); | |
String str (a + s, a + t); | |
if (token == String ("author")) { | |
std :: istringstream sin (str); | |
String tmp; | |
Vector <String> v; | |
while (sin >> tmp) { | |
v.clear (); | |
do { | |
if (tmp == String ("and")) { | |
break; | |
} | |
v.push_back (tmp); | |
} while (sin >> tmp); | |
aut.clear (); | |
aut.surname = v.back (); | |
for (int i = 0; i <SIZE (v) - 1; i ++) { | |
aut.name [i] = v [i]; | |
} | |
ref.authors.push_back (aut); | |
} | |
} else { | |
if (token == String ("title")) { | |
ref.title = str; | |
} else if (token == String ("journal")) { | |
ref.journal = str; | |
} else if (token == String ("publisher")) { | |
ref.publisher = str; | |
} else if (token == String ("year")) { | |
ref.year = to_number (str); | |
} else if (token == String ("volume")) { | |
ref.volume = to_number (str); | |
} else if (token == String ("number")) { | |
ref.number = to_number (str); | |
} else if (token == String ("pages")) { | |
bool flag = true; | |
for (int p = 0; p <SIZE (str); p ++) { | |
if (str [p] == '-') { | |
ref.page [0] = to_number (str.substr (0, p)); | |
ref.page [1] = to_number (str.substr (p + 2, SIZE (str))); | |
flag = false; | |
break; | |
} | |
} | |
if (flag) { | |
ref.page [0] = ref.page [1] = to_number (str); | |
} | |
} | |
} | |
i = pos; | |
if (a [pos] == '}') { | |
break; | |
} | |
} | |
ref.normalize (); | |
vector.push_back (ref); | |
} | |
std :: sort (ALL (vector)); | |
for (int i = 0; i <SIZE (vector); i ++) { | |
if (vector [i] .isarticle) { | |
vector [i] .article_print (i + 1); | |
} else { | |
vector [i] .book_print (i + 1); | |
} | |
} | |
} |
<? php
class Biblio
{
private $ finput = ";
private $ foutput = '';
public function __construct ($ finput = '', $ foutput = '')
{
$ this-> finput = $ finput;
$ this-> foutput = $ foutput;
}
private $ replace = array (
'author =' => '"author" =>',
'title =' => '"title" =>',
'journal =' => '"journal" =>',
'publisher =' => '"publisher" =>',
'year =' => '"year" =>',
'volume =' => '"volume" =>',
'number =' => '"number" =>',
'pages =' => '"pages" =>',
'author =' => '"author" =>',
'title =' => '"title" =>',
'journal =' => '"journal" =>',
'publisher =' => '"publisher" =>',
'year =' => '"year" =>',
'volume =' => '"volume" =>',
'number =' => '"number" =>',
'pages =' => '"pages" =>',
);
private $ data = array ();
public function createData ()
{
$ f = fopen ($ this-> finput, "r");
$ arr = array ();
$ tmp_st = '';
$ record = 0;
$ type = 'none';
while (! feof ($ f)) {
$ st = fgets ($ f);
$ st = trim ($ st);
if ($ st [0] == '@') {
$ type = 'none';
if ($ st == '@ article') $ type = 'article';
if ($ st == '@ book') $ type = 'book';
}
if ($ st [0] == '{') {
$ tmp_st = '';
}
if ($ st [0]! = '{' && $ st [0]! = '}' && $ st [0]! = '@') {
$ tmp_st. = $ st;
}
if ($ st [0] == '}') {
$ tmp_st = preg_replace ("/ [] {2,} /", '', $ tmp_st);
$ tmp_st = strtr ($ tmp_st, $ this-> replace);
$ tmp_st = '$ myarray = array ('. $ tmp_st. ');';
eval ($ tmp_st);
if (isset ($ myarray ['author'])) {
$ myarray ['author'] = $ this-> authorFormated ($ myarray ['author']);
}
$ myarray ['type'] = $ type;
$ arr [] = $ myarray;
$ record ++;
}
}
fclose ($ f);
$ this-> data = $ arr;
return $ this;
}
private function cmp ($ a, $ b)
{
return strcasecmp ($ a ["author"], $ b ["author"]);
}
private function authorFormated ($ st)
{
$ res = array ();
$ resst = ";
$ st = explode ('and', $ st);
foreach ($ st as $ numAutor => $ onepeople)
{
$ onepeople = trim ($ onepeople);
$ ar = explode (", $ onepeople);
$ cnt = count ($ ar);
if ($ cnt == 2) $ res [] = array ('surname' => array_pop ($ ar), 'name' => $ ar [0] {0});
if ($ cnt == 3) $ res [] = array ('surname' => array_pop ($ ar), 'name' => $ ar [0] {0}, 'patronymic' => $ ar [1] {0});
}
usort ($ res, array ('Biblio', 'cmp'));
$ cntres = count ($ res);
foreach ($ res as $ num => $ onepeople) {
if (isset ($ onepeople ['patronymic']))
$ resst. = $ onepeople ['surname']. ' '. $ onepeople [' name '].'. '. $ onepeople [' patronymic '].'. ';
else $ resst. = $ onepeople ['surname']. ' '. $ onepeople [' name '].'. ';
if ($ num <$ cntres-1) $ resst. = ',';
}
return $ resst;
}
private function cmp2 ($ a, $ b)
{
$ c = strcasecmp ($ a ["author"], $ b ["author"]);
if (($ c == 0) && isset ($ a ["volume"]) && isset ($ b ["volume"]))
$ c = ((int) $ a ["volume"] <(int) $ b ["volume"])? - 1: 1;
return $ c;
}
public function dataSort ()
{
$ data = $ this-> data;
usort ($ data, array ('Biblio', 'cmp2'));
$ this-> data = $ data;
return $ this;
}
public function saveData ()
{
$ data = $ this-> data;
$ fp = fopen ($ this-> foutput, "w");
foreach ($ data AS $ i => $ one) {
$ st = '';
if ($ one ['type'] == 'article') $ st = '['. ($ i + 1). ']'. $ one ['author']. ' '. $ one ["title"].
'//'. $ one ["journal"].
((isset ($ one ["volume"]) && $ one ["volume"]! = '')? ','. $ one ["volume"]: '').
((isset ($ one ["number"]) && $ one ["number"]! = '')? '('. $ one ["number"]. ')': '').
'-'. $ one ["year"].
((isset ($ one ["pages"]) && $ one ["pages"]! = '')? '- pp.'. $ one ["pages"]: '');
if ($ one ['type'] == 'book') $ st = '['. ($ i + 1). ']'. $ one ['author']. ' '. $ one ["title"].
((isset ($ one ["volume"]) && $ one ["volume"]! = '')? ', Vol.'. $ one ["volume"]: ''). ' - '. $ one ["publisher"].', '. $ one ["year"];
fwrite ($ fp, $ st.PHP_EOL);
}
fclose ($ fp);
return 1;
}
}
// type == article “Authors Title // Journal [, Volume] [(Number)] - year [- pages]”.
// type == book “Authors Title [, Vol. Volume] - Publisher, Year ”.
$ bi = new Biblio ('bibtex.in', 'bibtex.out');
$ bi-> createData () -> dataSort () -> saveData ();
?>
use function eval (), usort (). acess to char of string by type {i}
see solve in attach file this mail
bibtex.in
need valid permission to create file bibtex.out
Comments
To leave a comment
Running server side scripts using PHP as an example (LAMP)
Terms: Running server side scripts using PHP as an example (LAMP)