[[TableOfContents]] ---- == Step 1 == === 결과 === * 실행: java anagram.FindAnagram < 입력파일> 출력파일 * 테스트환경: P3 1G, 512MB, j2sdk1.4.0, 입력데이터-[http://zeropage.org/pds/2002104113433/word.lst 172823건] * 결과: 14130 ms == Step 2 == === 개선사항 === * genKey() 메소드의 성능 개선. qsort2([http://www.cs.bell-labs.com/cm/cs/pearls/sortanim.html ProgrammingPerals 참고]) 이용. === 결과 === * 실행: java anagram.FindAnagram < 입력파일> 출력파일 * 테스트환경: P3 1G, 512MB, j2sdk1.4.0, 입력데이터-[http://zeropage.org/pds/2002104113433/word.lst 172823건] * 결과: 10885 ms == Step 3 == === 개선사항 === * 테스트중 OS 표준입력과 자바에서 직접 파일을 읽는 것과는 별 차이가 없지만, OS 표준 출력이 자바에서 직접 파일출력하는것 보다 상당히 느림을 발견. 자바에서 직접 출력하도록 코드 변경 === 결과 === * 실행: java anagram.FindAnagram 출력파일 < 입력파일 * 테스트환경: P3 1G, 512MB, j2sdk1.4.0, 입력데이터-[http://zeropage.org/pds/2002104113433/word.lst 172823건] * 결과: 7270 ms == Step 4 == === 개선사항 === * String 객체의 생성을 줄임.(대략 300ms 정도 줄어듬) : 마이크로 튜닝으로 넘어갈수록 노력 대비 결과가 크지 않음. * Class, method 이름 refactoring === 결과 === * 실행: java anagram.Anagram 출력파일 < 입력파일 * 테스트환경: P4 1.8, 512MB, j2sdk1.4.1-b21, 입력데이터-[http://zeropage.org/pds/2002104113433/word.lst 172823건] * 결과: 3047 ms * 분석: 예전에 우스개 소리로, 프로그램을 빠르게 하려면 컴퓨터를 업그레이드 하라더니, 웃을일이 아니다 -_-; == To Do == * [[HTML()]]테스트 사양에 독립적인 속도 측정방법 생각[[HTML()]] * 다른 알고리즘, 자료구조 생각요. * Profiling * 복잡도 구해보기 == Sources == === 상대시간 비교를 위한 애플릿 === {{{~cpp import java.awt.Graphics; import java.applet.Applet; import java.io.*; import java.util.*; public class PowerTest extends Applet { long elapsed = 0; AnagramTest anagram; public void start() { elapsed = System.currentTimeMillis(); InputStream in = null; anagram = new AnagramTest(); for( int i=0; i<10000; i++ ) { anagram.add( "test" ); anagram.add( "aah" ); anagram.add( "aahed" ); anagram.add( "aahing" ); anagram.add( "aahs" ); anagram.add( "aal" ); anagram.add( "aalii" ); anagram.add( "aaliis" ); anagram.add( "aals" ); anagram.add( "aardvark" ); anagram.add( "aardvarks" ); anagram.add( "aardwolf" ); anagram.add( "aardwolves" ); anagram.add( "aargh" ); anagram.add( "aarrgh" ); anagram.add( "aarrghh" ); anagram.add( "aas" ); anagram.add( "aasvogel" ); anagram.add( "aasvogels" ); anagram.add( "ab" ); anagram.add( "aba" ); anagram.add( "abaca" ); anagram.add( "abacas" ); anagram.add( "abaci" ); anagram.add( "aback" ); } elapsed = System.currentTimeMillis() - elapsed; repaint(); } public void paint( Graphics g ) { g.drawString( "JVM info:", 10, 20 ); g.drawString( "....vendor : " + System.getProperty( "java.vm.vendor"), 10, 35 ); g.drawString( "....version: " + System.getProperty( "java.vm.version"), 10, 50 ); g.drawString( "....name: " + System.getProperty( "java.vm.name"), 10, 65 ); if( elapsed != 0 ) g.drawString( "Estimated power: " + String.valueOf(elapsed), 10, 90 ); } } class AnagramTest { private Hashtable result = new Hashtable(); private byte [] seq; public AnagramTest() { } public void add( String str ) { List list; Object key = genKey( str ); Object value = result.get( key ); if( value == null ) { list = new ArrayList(); result.put( key, list ); } else list = (ArrayList)value; list.add( str ); } private Object genKey( String str ) { seq = str.getBytes(); qsort2( 0, seq.length-1 ); return java.nio.ByteBuffer.wrap( seq ); } private void swap( int i, int j ) { byte t = seq[i]; seq[i] = seq[j]; seq[j] = t; } private void qsort2( int l, int u ) { if( l >= u ) return; int i = l; int j = u+1; while( true ) { do i++; while (i <= u && seq[i] < seq[l]); do j--; while (seq[j] > seq[l]); if( i > j ) break; swap( i, j ); } swap( l, j ); qsort2( l, j-1 ); qsort2( j+1, u ); } } }}} === Step 1 === {{{~cpp package anagram; import java.io.*; import java.util.*; public class FindAnagram { Hashtable result = new Hashtable(); public FindAnagram( InputStream in ) throws Exception { BufferedReader reader = new BufferedReader( new InputStreamReader( in )); String readLine; while( (readLine=reader.readLine()) != null ) { putTable( readLine.trim() ); } } private void putTable( String str ) { List list; Object key = genKey( str ); Object value = result.get( key ); if( value == null ) { list = new ArrayList(); result.put( key, list ); } else list = (ArrayList)value; list.add( str ); } private Object genKey( String str ) { Hashtable table = new Hashtable(); Object value; String ch; for( int i=0; i= u ) return; int i = l; int j = u+1; while( true ) { do i++; while (i <= u && seq[i] < seq[l]); do j--; while (seq[j] > seq[l]); if( i > j ) break; swap( i, j ); } swap( l, j ); qsort2( l, j-1 ); qsort2( j+1, u ); } public void print( PrintStream out ) { List list; for( Enumeration e=result.elements(); e.hasMoreElements(); ) { list = (ArrayList)e.nextElement(); for( Iterator item=list.iterator(); item.hasNext(); ) { out.print( item.next() ); out.print( " " ); } out.println(); } } public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); FindAnagram anagram = new FindAnagram( System.in ); long end = System.currentTimeMillis(); anagram.print( System.out ); long printEnd = System.currentTimeMillis(); System.out.println( "수행시간: " + (end-start) + " ms" ); System.out.println( "수행시간(print): " + (printEnd-start) + " ms" ); } } }}} === Step 3 === {{{~cpp package anagram; import java.io.*; import java.util.*; public class FindAnagram { private Hashtable result = new Hashtable(); private byte [] seq; public FindAnagram( InputStream in ) throws Exception { BufferedReader reader = new BufferedReader( new InputStreamReader( in )); String readLine; while( (readLine=reader.readLine()) != null ) putTable( readLine.trim() ); } private void putTable( String str ) { List list; Object key = genKey( str ); Object value = result.get( key ); if( value == null ) { list = new ArrayList(); result.put( key, list ); } else list = (List)value; list.add( str ); } private Object genKey( String str ) { seq = str.getBytes(); qsort2( 0, seq.length-1 ); return java.nio.ByteBuffer.wrap( seq ); } private void swap( int i, int j ) { byte t = seq[i]; seq[i] = seq[j]; seq[j] = t; } private void qsort2( int l, int u ) { if( l >= u ) return; int i = l; int j = u+1; while( true ) { do i++; while (i <= u && seq[i] < seq[l]); do j--; while (seq[j] > seq[l]); if( i > j ) break; swap( i, j ); } swap( l, j ); qsort2( l, j-1 ); qsort2( j+1, u ); } public void print( PrintStream out ) { List list; for( Enumeration e=result.elements(); e.hasMoreElements(); ) { list = (List)e.nextElement(); for( Iterator item=list.iterator(); item.hasNext(); ) { out.print( item.next() ); out.print( " " ); } out.println(); } } public static void main( String[] args ) throws Exception { if( args.length != 1 ) { System.out.println( "usage: java anagram.FindAnagram out_file < input_file" ); System.exit( -1 ); } long start = System.currentTimeMillis(); FindAnagram anagram = new FindAnagram( System.in ); long end = System.currentTimeMillis(); BufferedOutputStream out = null; try { out = new BufferedOutputStream( new FileOutputStream( args[0] )); anagram.print( new PrintStream( out )); } finally { if( out != null ) try { out.close(); } catch( Exception e ) {} } long printEnd = System.currentTimeMillis(); System.out.println( "수행시간: " + (end-start) + " ms" ); System.out.println( "수행시간(print): " + (printEnd-start) + " ms" ); } } }}} === Step 4 === {{{~cpp package anagram; import java.io.*; import java.util.*; import java.nio.*; public class Anagram { private Hashtable result = new Hashtable( 512 ); public Anagram() {} public Anagram( InputStream in ) throws Exception { BufferedReader reader = new BufferedReader( new InputStreamReader( in )); String readLine; while( (readLine=reader.readLine()) != null ) if( readLine.length() != 0 ) add( readLine ); } public void add( String str ) { ByteBuffer key = ByteBuffer.wrap( str.getBytes() ); qsort2( key, 0, key.capacity()-1 ); Object value = result.get( key ); if( value == null ) { List list = new ArrayList(); result.put( key, list ); list.add( str ); } else ((List)value).add(str); } private void swap( ByteBuffer buf, int i, int j ) { byte t = buf.get(i); buf.put( i, buf.get(j)); buf.put( j, t ); } private void qsort2( ByteBuffer buf, int l, int u ) { if( l >= u ) return; int i = l; int j = u+1; while( true ) { do i++; while (i <= u && buf.get(i) < buf.get(l)); do j--; while (buf.get(j) > buf.get(l)); if( i > j ) break; swap( buf, i, j ); } swap( buf, l, j ); qsort2( buf, l, j-1 ); qsort2( buf, j+1, u ); } public void print( PrintStream out ) { List list; for( Enumeration e=result.elements(); e.hasMoreElements(); ) { list = (List)e.nextElement(); for( Iterator item=list.iterator(); item.hasNext(); ) { out.print( item.next() + " " ); } out.println(); } } public static void main( String[] args ) throws Exception { if( args.length != 1 ) { System.out.println( "usage: java anagram.FindAnagram out_file < input_file" ); System.exit( -1 ); } long start = System.currentTimeMillis(); Anagram anagram = new Anagram( System.in ); BufferedOutputStream out = null; try { out = new BufferedOutputStream( new FileOutputStream( args[0] )); anagram.print( new PrintStream( out )); } finally { if( out != null ) try { out.close(); } catch( Exception e ) {} } long end = System.currentTimeMillis(); System.out.println( "Elapsed time: " + (end-start) + " ms" ); } } }}} ---- ClassifyByAnagram