/* 
 * @(#)PalindromeArray.java  1.0 Apr 26, 2008 
 * 
 *  The MIT License 
 * 
 *  Copyright (c) 2008 Malachi de AElfweald <[email protected]> 
 * 
 *  Permission is hereby granted, free of charge, to any person obtaining a copy 
 *  of this software and associated documentation files (the "Software"), to deal 
 *  in the Software without restriction, including without limitation the rights 
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 *  copies of the Software, and to permit persons to whom the Software is 
 *  furnished to do so, subject to the following conditions: 
 * 
 *  The above copyright notice and this permission notice shall be included in 
 *  all copies or substantial portions of the Software. 
 * 
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 *  THE SOFTWARE. 
 */ 
//package org.eoti.math; 
 
import java.math.BigInteger; 
import java.util.Iterator; 
import java.util.concurrent.ConcurrentHashMap; 
 
public class PalidromeArray 
  implements Iterable<BigInteger> 
{ 
  protected static final BigInteger TWO = BigInteger.valueOf(2); 
  protected ConcurrentHashMap<BigInteger,BigInteger> array; 
  protected BigInteger totalLength, halfLength; 
  protected boolean isEven = true; 
 
  public static PalidromeArray fromString(String s) 
  { 
    String[] arr = s.split("\\|"); 
    BigInteger[] bi = new BigInteger[arr.length]; 
    for(int i=0; i<arr.length; i++) 
      bi[i] = new BigInteger(arr[i]); 
 
    return new PalidromeArray(bi); 
  } 
 
  public PalidromeArray(PalidromeArray array) 
  { 
    this.totalLength = array.totalLength; 
    this.halfLength = array.halfLength; 
    this.isEven = array.isEven; 
 
    this.array = new ConcurrentHashMap<BigInteger,BigInteger>(); 
    for(BigInteger index : array.array.keySet()) 
      this.array.put(index, array.array.get(index)); 
  } 
 
  public PalidromeArray(BigInteger[] array) 
  { 
    this.totalLength = BigInteger.valueOf(array.length); 
    this.halfLength = totalLength.divide( TWO ); 
    if( MathUtil.isOdd(totalLength)) 
    { 
      isEven = false; 
      halfLength=halfLength.add(BigInteger.ONE); 
    } 
    this.array = new ConcurrentHashMap<BigInteger,BigInteger>(); 
 
    BigInteger index = BigInteger.ZERO; 
    for(BigInteger bi : array) 
    { 
      this.array.put( index, bi ); 
      index = index.add(BigInteger.ONE); 
    } 
  } 
 
  public PalidromeArray(BigInteger totalLength) 
  { 
    this.totalLength = totalLength; 
    this.halfLength = totalLength.divide( TWO ); 
    if( MathUtil.isOdd(totalLength)) 
    { 
      isEven = false; 
      halfLength=halfLength.add(BigInteger.ONE); 
    } 
    array = new ConcurrentHashMap<BigInteger,BigInteger>(); 
  } 
 
  public String toString() 
  { 
    StringBuilder sb = new StringBuilder(); 
    boolean first = true; 
    for(BigInteger bi : this) 
    { 
      if(!first) sb.append("|"); 
      sb.append(bi); 
      first = false; 
    } 
 
    return sb.toString(); 
  } 
 
  public BigInteger halfLength(){return halfLength;} 
  public BigInteger totalLength(){return totalLength;} 
  public BigInteger get(BigInteger position) 
  { 
    /** 
     * {1,4,6,4,1} would have {1,4,6} in our array 
     * 0: return 1 
     * 1: return 4 
     * 2: return 6 
     * 3: return 4 
     * 4: return 1 
     * totalLength = 5 
     * halfLength = 3 
     * get(0) returns #0 
     * get(1) returns #1 
     * get(2) returns #2 
     * get(3) returns #1 
     * get(4) returns #0 
     * 
     * {1,3,3,1} would have {1,3} in our array 
     * array.length = 2 
     * 0: return 1 
     * 1: return 3 
     * 2: return 3 
     * 3: return 1 
     * totalLength = 4 
     * halfLength = 2 
     * get(0) returns #0 
     * get(1) returns #1 
     * get(2) returns #1 
     * get(3) returns #0 
     */ 
    if(position.subtract(halfLength).signum() < 0) 
      return array.get(position); 
 
    BigInteger mid = halfLength.subtract(BigInteger.ONE); 
 
    if(isEven) 
      return array.get( mid.subtract( position.subtract(halfLength) )); 
 
    return array.get( mid.subtract( position.subtract(mid) )); 
  } 
  public void set(BigInteger position, BigInteger value){array.put(position, value);} 
 
  public Iterator<BigInteger> iterator() 
  { 
    return new PalidromeArrayIterator(this); 
  } 
 
  class PalidromeArrayIterator 
  implements Iterator<BigInteger> 
  { 
    protected PalidromeArray array; 
    protected BigInteger position = BigInteger.ZERO; 
 
    public PalidromeArrayIterator(PalidromeArray array) 
    { 
        this.array = array; 
    } 
 
    public boolean hasNext() 
    { 
      return array.totalLength.subtract(position).signum() > 0; 
    } 
 
    public BigInteger next() 
    { 
      BigInteger index = position; 
      position = position.add(BigInteger.ONE); 
      return array.get(index); 
    } 
 
    public void remove() 
    { 
      throw new UnsupportedOperationException("Not supported"); 
    } 
  } 
} 
 
    
     
     
     
     
     
   |     
 
 |