Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Ruby: Общие вопросы > Егэ-шные задачки


Автор: Neud 11.12.2009, 15:36
Прошу замечаний и предложений по следующей задаче:

В соревнованиях по многоборью (из M видов спорта) участвуют N спортсменов (N < 1000) . На вход программе в первой строке подается число спортсменов N, во второй – число видов спорта M. В каждой из последующих N строк находится информация в следующем формате: 

<Фамилия> <Имя> <Баллы> 

где <Фамилия> – строка, состоящая не более, чем из 20 символов без пробелов, <Имя> – строка, состоящая не более, чем из 12 символов без пробелов, <Баллы> – M целых чисел, обозначающие количество баллов, набранных спортсменом в каждом из видов многоборья. 
<Фамилия> и <Имя>, <Имя> и <Баллы>, а также отдельные числа в поле <Баллы> разделены ровно одним пробелом. Пример входных строк: 

3
4
Иванов Сергей 100 30 78 13
Петров Антон 90 16 98 14
Сидоров Юрий 100 70 30 21 

Программа должна выводить результирующую таблицу, содержащую список спортсменов, отсортированный по убыванию суммы баллов, набранные суммы и занятые места.
В данном случае программа должна вывести 

Иванов Сергей 221 1
Сидоров Юрий 221 1
Петров Антон 218 2

Код
$stdin = File.open('c:\in.txt')
list=[]

N=gets.to_i
gets

N.times{
    lastname, firstname, *balls=gets.split          
    name=lastname+' '+firstname
    ball=eval balls.join('+')
    list<<[name, ball]}
    
list=list.sort_by{|name,ball| ball}.reverse

place=1
prev_ball=0

list.each{|name,ball|
     place+=1 if ball<prev_ball
     puts "#{name} #{ball} #{place}"
     prev_ball=ball}


Автор: Pitlord 11.12.2009, 19:01
Вроде бы на ЕГЭ только Pascal, C/C++, Basic разрешены, нет?

Автор: shine 11.12.2009, 20:01
У топикстартера уже достаточно хороший вариант, но можно еще лучше:
Код

$stdin = File.open('c:\in.txt')
list = {}

N = gets.to_i
gets

N.times do
  lastname, firstname, *balls = gets.split
  sum = eval(balls.join('+'))
  list[sum].nil? ? list[sum] = [lastname+' '+firstname] : list[sum] << lastname+' '+firstname
end

list.sort.reverse.each_with_index do |item, index|
  item[1].each do |name|
    puts "#{name} #{item[0]} #{index+1}"
  end
end

Автор: Neud 11.12.2009, 20:43
Цитата(Pitlord @ 11.12.2009,  19:01)
Вроде бы на ЕГЭ только Pascal, C/C++, Basic разрешены, нет?

Нет. Разрешено всё.

Добавлено @ 20:47
shine, спасибо. 

Еще задачка ЕГЭ:

На вход программы подаются прописные латинские буквы, ввод этих символов заканчивается точкой. Напишите эффективную по времени работы и по используемой памяти программу, которая будет определять, можно ли переставить эти буквы так, чтобы получился палиндром (палиндром читается одинаково слева направо и справа налево). Программа должна вывести ответ «Да» или «Нет», а в случае ответа «Да» – еще и сам полученный палиндром (первый в алфавитном порядке). 
Пример входной строки: 

GAANN 

Пример выходных данных: 

Да
ANGNA

Код
all=gets.chomp.split('.').first.split('') #выделяем текст до точки и преобразуем в массив
odds=all.select{|char| all.count(char).odd?}    #массив букв, встречающихся нечетное число раз
if odds.size>1
  puts 'Нет'
else
  puts 'Да'
  evens=all-odds
  s=evens.uniq.map{|char| char*(evens.count(char)/2)}.sort.join  #массив четных делим пополам (а проще можно?)
  puts s+odds.join+s.reverse  #выводим половину четных, одну нечетную, четные наоборот
end


Автор: Neud 12.12.2009, 00:57
shine, если использовать хэш, то первую задачу можно и так написать:

Код

$stdin = File.open('c:\in.txt')
list={}

gets.to_i.times do
    lastname, firstname,*balls=gets.split          
    list[lastname+' '+firstname]=eval balls.join('+')
end

list.sort_by{|name,ball| ball}.reverse.each do |name,ball| 
  puts "#{name} #{ball} #{list.values.uniq.sort.reverse.index(ball)+1}"
end


Правда, полные тезки сольются.

Автор: source777 12.12.2009, 15:27
shineNeud, какие хеши, вы чего?
Одинаковые имя с фамилией может встречаться сколько угодно раз, не говоря уж о сумме баллов, я уж не говорю про eval для простейшего сложения, стыд и позор  smile 

Код

$stdin = File.open(ARGV[0] || 'c:\in.txt')
list = []

n = gets.to_i
m = gets.to_i

n.times do
  lastname, firstname, *balls=gets.split          
  name = lastname+' '+firstname
  ball = balls.slice(0, m).inject(0){|acc, ball| acc+=ball.to_i }
  list << [name, ball]
end    

list = list.sort_by{|name, ball| ball}.reverse

place = 1
prev_ball = 0

list.each do |name, ball|
  place+=1 if ball<prev_ball
  puts [name, ball, place].join("\t")
  prev_ball=ball
end

Автор: source777 13.12.2009, 16:02
Модератор: Тема почищена от оффтопика 

Автор: Neud 13.12.2009, 22:28
source777

1) согласно условию ЕГЭ предусматривать отклонения от формата ввода не требуется. Так что "стыд и позор" именно вам, а не нам - за абсолютно лишний код.

2) eval "для простейшего сложения" - это плохо, а inject - хорошо?

Автор: source777 15.12.2009, 12:01
Neud
1) решения с хешами - абсолютно неправильные вне зависимости от формата, т.к. в условии нигде не сказано, что имена не могут совпадать или сумма баллов у всех разная.
2) да, eval для чего-либо - это ужасно, когда можно обойтись без него
3) не забывай, что ты сюда пришёл за помощью и критикой, так что насчёт абсолютно лишнего кода я запомню и тебе больше помогать не буду, пока не извинишься.  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)