Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задача: Города. Покритикуйте. 
:(
    Опции темы
m1st
Дата 19.7.2010, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Цитата
Широко известна игра "Города". Называется какой-нибудь город, допустим, "Саратов". Кончается на "в", значит требуется назвать другой город, у которого в названии первая буква "в". Это может быть "Воронеж". Следующий город должен начинаться на "ж" и т.д. Запрещено повторять название городов. Надо написать программу, которая из набора названий городов (все названия разные) строит цепочку максимальной длины.

Привет, решение данной задачи на Java. Покритикуйте. (файл-список городов в аттаче):
Код

package OlympicExercises;

import java.io.*;
import java.util.ArrayList;

public class g6_1011 {
public static void main(String[] args) throws IOException {
BufferedReader in2 = new BufferedReader(new FileReader("src/OlympicExercises/cities.txt"));
String city2;
ArrayList cities = new ArrayList();
while((city2 = in2.readLine()) != null)
cities.add(city2);
in2.close();

String city3, firstChar;
boolean[] used = new boolean[cities.size()];
ArrayList citiesSequenceTMP = new ArrayList(),
citiesSequence = new ArrayList();
for(int i4 = 0; i4 < cities.size(); i4++) {
for(int i3 = 0; i3 < cities.size(); i3++) {
used[i3] = false; }
String city = cities.get(i4).toString();
String lastChar = city.substring(city.length()-1);
for(int i2 = 0; i2 < cities.size(); i2++) {
for(int i = 0; i < cities.size(); i++) {
//                if(cities.get(i).toString().equals(city)) continue;
if(used[i]) continue;
city3 = cities.get(i).toString();
firstChar = city3.substring(0, 1).toLowerCase();
if(firstChar.equals(lastChar)) {
citiesSequenceTMP.add(cities.get(i));
lastChar = city3.substring(city3.length()-1);
used[i] = true;
}
}
if(citiesSequenceTMP.size() > citiesSequence.size()) {
citiesSequence.clear();
citiesSequence.addAll(citiesSequenceTMP);
citiesSequenceTMP.clear();
}
if(citiesSequenceTMP.size() < citiesSequence.size())
citiesSequenceTMP.clear();
}
}
System.out.println(citiesSequence + " = " + citiesSequence.size() + " cities");
}
}


Это сообщение отредактировал(а) m1st - 19.7.2010, 17:49

Присоединённый файл ( Кол-во скачиваний: 14 )
Присоединённый файл  cities.txt 1,73 Kb
PM MAIL   Вверх
Kircul
Дата 19.7.2010, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 20.2.2007

Репутация: 6
Всего: 7



Первое что можно исправить (мое личное мнение) - это при чтении из файла создать коллекцию для поиска такого вида:
Код

Map<Character, Set<String>> citiesIndex = ...; // key - прервая буква города, value - имена городов начинающихся на эту букву

Она поможет исправить поиск города по первой букве.

При использовании какого-нибудь города его просто удалять из коллекции (естественно из копии оригинальной коллекции, созданной при чтении из файла), а не использовать массив used.

Желательно отформатировать исходный код перед отправкой на форум (а то уж очень не удобно читать с такими страшными отступами)

В Java в именах пакетов не принято использовать верхний регистр, а имена классов должно начинаться с большой буквы. 

Данный код:
Код

        String city2;
        ArrayList cities = new ArrayList();
        while((city2 = in2.readLine()) != null)
        cities.add(city2);

по моему лучше смотриться так (но это только мое мнение и к нему не обязательно прислушиваться):
Код
 
        ArrayList cities = new ArrayList();
        for(String city2;(city2 = in2.readLine()) != null;)
                cities.add(city2);


Это сообщение отредактировал(а) Kircul - 19.7.2010, 16:55
PM   Вверх
ivanovpv
Дата 19.7.2010, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Алгоритм конечно атас... Так сказать brute-force в самом жестоком виде - так и ребенок напишет. Мне кажется тут надо в первую голову думать над собственно алгоритмом выстраивания самой длинной цепочки, а не о качестве кода - который тоже не ахти. 


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
Kircul
Дата 19.7.2010, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 20.2.2007

Репутация: 6
Всего: 7



"Premature optimization is the root of all evil" ©
ИМХО, не стоит сходу все выкидывать и писать заново, для начала сойдет и составление коллекции citiesIndex, а уж дальше смотреть что еще можно изменить.
PM   Вверх
m1st
Дата 19.7.2010, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Цитата(Kircul @  19.7.2010,  16:39 Найти цитируемый пост)
Первое что можно исправить (мое личное мнение) - это при чтении из файла создать коллекцию для поиска такого вида:
Она поможет исправить поиск города по первой букве.
Действительно, отпадает необходимость хранить первую букву в плохочитаемом поле. 
Set<String> сразу решает проблему с дубликатами и ускорением поиска по hashCode().

Цитата(Kircul @  19.7.2010,  16:39 Найти цитируемый пост)
Желательно отформатировать исходный код перед отправкой на форум (а то уж очень не удобно читать с такими страшными отступами)
Сорри, код отформатировал.

Цитата(Kircul @  19.7.2010,  16:39 Найти цитируемый пост)
по моему лучше смотриться так (но это только мое мнение и к нему не обязательно прислушиваться):
По-моему тоже так лучше. Если честно, первый раз увидел такую конструкцию... smile

Спасибо!
PM MAIL   Вверх
ki6opr
Дата 20.7.2010, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 20.12.2006

Репутация: нет
Всего: нет



кстати если заранее неизвестен размер списка, лучше использовать LinkedList, ArrayList основан на массиве и создается с некоторым дефолтным по размеру, когда кол-во элементов превышает размер массива, создается новый и в него копируются значения старого, в LinkedList этого нет.
резюме: 
ArrayList - быстр при доступе по индексу но медленный и неэкономно расходует ресурсы если неизвестно кол-во элементов
LinkedList - быстр при добавлении новых элементов, но медленее при обращении по индексу

+ если вам напрямую ненужны методы ArrayList лучше тип переменной указать как List, работа с интерфейсами или абстрактными классами делает систему более легкой для внесения изминений
мое маленькое имхо smile 

Это сообщение отредактировал(а) ki6opr - 20.7.2010, 09:43
PM MAIL ICQ   Вверх
Kircul
Дата 20.7.2010, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 20.2.2007

Репутация: 6
Всего: 7



Цитата(ki6opr @  20.7.2010,  07:55 Найти цитируемый пост)
+ если вам напрямую ненужны методы ArrayList лучше тип переменной указать как List

Однозначно верно.

[offtopic]
Цитата(ki6opr @  20.7.2010,  07:55 Найти цитируемый пост)
если заранее неизвестен размер списка, лучше использовать LinkedList

А вот это уже спорно, в теории все должно быть так как вы говорите, но на практике ArrayList работает быстрее (при добавлении елементов в конец списка). Сам наткнулся на эти грабли вот тут. LinkedList хорош тогда когда необходимо проводить довольно много добавлений в середину списка.
[/offtopic]
PM   Вверх
jk1
Дата 20.7.2010, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Цитата

 ArrayList основан на массиве и создается с некоторым дефолтным по размеру, когда кол-во элементов превышает размер массива, создается новый и в него копируются значения старого, в LinkedList этого нет.

Эффект можно минимизировать грамотным заданием capacity при создании листа.
Полностью поддерживаю Kircul, LinkedList предназначен для специфических случаев:
Цитата

If you frequently add elements to the beginning of the List or iterate over the List to delete elements from its interior, you should consider using LinkedList. These operations require constant-time in a LinkedList and linear-time in an ArrayList. But you pay a big price in performance. Positional access requires linear-time in a LinkedList and constant-time in an ArrayList. Furthermore, the constant factor for LinkedList is much worse. If you think you want to use a LinkedList, measure the performance of your application with both LinkedList and ArrayList before making your choice; ArrayList is usually faster.



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
ivanovpv
Дата 20.7.2010, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Если говорить о мелочной оптимизации не самого лучшего алгоритма и кода, то я бы посоветовал:
а) Вместо массива boolean использовать BitSet
б) Вместо String использовать StringBuffer/StringBuilder - это даст существенный выигрыш на текстовых операциях, типа:
Код

                    StringBuffer city = cities.get(i);  //щетаем, что cities содержит StringBuffer'ы - см. далее
                    char firstChar = Character.toLowerCase(city.charAt(0));

в) В циклах убрать постоянное обращение к методу size() - примерно так:
Код

   for (int size4=cities.size(), i4 = 0; i4 < size4; i4++)
        {

        }

г) Вообще постоянное создание стековых переменных в теле цикла - это тоже не очень хорошо - известно что это замедляет скорость
д) Красяво, да и быстрее по скорости можно было бы вместо   ArrayList cities = new ArrayList(); объявить:
Код

  List<StringBuffer> cities = new List<StringBuffer>();

    1) List дешевле ArrayList
    2) Компилятор знает тип объекта внутри списка, так что операция каста будет оптимизирована


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
jk1
Дата 20.7.2010, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Цитата

 List дешевле ArrayList

ivanovpv
Вы не могли бы пояснить эту мысль? На первый взгляд из преимуществ только loose coupling и возможность подмены реализации. Откуда прирост в скорости?
Я уже не говорю о том, что List - это интерфейс, его инстанс создать никак нельзя. 


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
powerOn
Дата 20.7.2010, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(ivanovpv @  20.7.2010,  15:17 Найти цитируемый пост)
city.charAt(0)

А в чем тут выигрыш?

В классе StringBuffer:
Код

public synchronized char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
    }


В классе String:
Код

    public char charAt(int index) {
        if ((index < 0) || (index >= count)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index + offset];
    }


В том, что операция сложения нужна лишняя?



--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ki6opr
Дата 21.7.2010, 04:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 20.12.2006

Репутация: нет
Всего: нет



Если уж заменять String операции то тогда на StringBuilder, потому как он не thread save, и не будет затрачено время на блокирование. как бы syncronized нехило отъедает ресурсов.

Кстати я насколько знаю компилятор проводит оптимизацию и часто операции с String заменяются на StringBuilder

и плюс много к грамотному заданию Capacity и BitSet. булин в яве сделан через integer если я правильно помню ?

Это сообщение отредактировал(а) ki6opr - 21.7.2010, 04:54
PM MAIL ICQ   Вверх
ivanovpv
Дата 21.7.2010, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Цитата(powerOn @  20.7.2010,  15:57 Найти цитируемый пост)
А в чем тут выигрыш?

Не так все однозначно... Я неверно указал на StringBuffer, надо использовать StringBuilder. Прогоните такой тестик:
Код

public static void main(String[] args)
    {
        String s="abrakadabra";
        testString(s);
        testStringBuilder(s);
        testStringBuffer(s);
    }

    public static void testString(String test)
    {
        String s=new String(test);
        char ch;
        long start=System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
            s.charAt(0);
        long end=System.currentTimeMillis();
        System.out.println("String: "+(end-start)+" - millis");
    }

    public static void testStringBuilder(String test)
    {
        StringBuilder s=new StringBuilder(test);
        char ch;
        long start=System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
            s.charAt(0);
        long end=System.currentTimeMillis();
        System.out.println("StringBuilder: "+(end-start)+" - millis");
    }

    public static void testStringBuffer(String test)
    {
        StringBuffer s=new StringBuffer(test);
        char ch;
        long start=System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
            s.charAt(0);
        long end=System.currentTimeMillis();
        System.out.println("StringBuffer: "+(end-start)+" - millis");
    }


На моей системе выдача такая:
Код

String: 281 - millis
StringBuilder: 234 - millis
StringBuffer: 4797 - millis


Так что эффективнее все же StringBuilder

Это сообщение отредактировал(а) ivanovpv - 21.7.2010, 09:08


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
powerOn
Дата 21.7.2010, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



ivanovpv, тест конечно верный. StringBuilder работает быстрее. Вот только 50 мс разница на сто миллиардов операции практически не имеет влияния на производительность. Не такое это уж и узкое место. Разница в реализации метода charAt для классов String и StringBuilder минимальна:

String:
Код

public char charAt(int index) {
        if ((index < 0) || (index >= count)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index + offset];
    }


AbstractStringBuilder:
Код

public char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
    }


Выигрыш последнего только за счет отсутствия операции index + offset. На таком огромном количестве операции, что вы проводили при тестировании,  разница может быть и видна. Но на миллионе уже не так.
 


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ivanovpv
Дата 21.7.2010, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Цитата(powerOn @  21.7.2010,  11:26 Найти цитируемый пост)
Разница в реализации метода charAt для классов String и StringBuilder минимальна:

1) Тут речь идет не столько о методе charAt(), а о других методах. Смысл то в том, что если есть массовые операции над строками - лучше использовать StringBuilder
2) Выигрыш я думаю не в арифметике, а в блокировках

А вообще согласен, все это копейки  smile 



--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1033 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.