require "sets"
require "maps"


class TopologicalSpace < Set
  attr_accessor :top

  def complete!
    loop do
      news = Set[]
      @top.each_pair do |x, y|
	z = x & y
	news.push z if !@top.has?(z) && !news.has?(z)
	z = x | y
	news.push z if !@top.has?(z) && !news.has?(z)
      end
      if news.empty?
	break
      else
	@top.concat news
	@top.sort!
      end
    end
  end
  
  def self.new(space, top)
    t = cast(space)
    t.top = top
    t
  end

  def ==(other)
    super and @top == other.top
  end

  def topological_space?
    return false unless @top.subset?(self)
    return false unless @top.exist{|x| x.size == 0}
    return false unless @top.exist{|x| x.size == size}
    @top.each_pair do |s, t|
      return false if !@top.has?(s & t)
      return false if !@top.has?(s | t)
    end
    true
  end

  def connected?
    @top.each do |o0|
      next if o0.size == 0
      @top.each do |o1|
	next if o1.size == 0
	return false if (o0&o1).empty? and (o0|o1).size == size
      end
    end
    true
  end

  def T0?
    each_pair {|x, y|
      unless @top.exist{|o|
	  o.has?(x) && !o.has?(y) || !o.has?(x) && o.has?(y)
	}
	return false
      end
    }
    true
  end

  def T1?
    each {|x|
      each {|y|
	next if x == y
	unless @top.exist{|o| o.has?(x) and not o.has?(y)}
	  return false
	end
      }
    }
    true
  end

  def T2?
    each_pair {|x, y|
      unless @top.exist{|o0| o0.has?(x) and @top.exist{|o1|
	    o1.has?(y) and (o0|o1).empty?
	  }
	}
	return false
      end
    }
    true
  end

  def homeo0?(other)
    return nil if top.size != other.top.size
    maps = other.bijections(self)
    maps.each do |map|
      return map if continuous?(map)
    end
    nil
  end

  require "groups"
  require "permutation"
  def (Trans = []).[](n)
    super || self[n] =  PermGr.create(n)
  end

  def homeo?(other) # other must be in domain of permutation of numbers
    return nil if top.size != other.top.size
    Trans[size].each do |map|
      if other.top.exist{|o| ! top.has?(map.lact(o).Set.sort!)}
	;
      else
	return map
      end
    end
    nil
  end

  #### topological map ####
  
  def continuous?(map)
    source, target = map.source, map.target
    target.top.all do |s|
      top.has? map.inv_image(s)
    end
  end

  def homeomorphism?(map)
    map.bijective? and continuous?(map)
  end
end

class TopGenerator0 < Set
  castable

  def each
    self.Set.each_subset0 do |s|
      yield s
    end
  end

  def topology0?(x)
    n = size
    x.each_pair do |s, t|
      u = s & t
      if !u.empty? && !x.has?(u)
	return false
      end
      u = s | t
      if u.size != n && !x.has?(u)
	return false
      end
    end
    true
  end

  def each_topology
    each_subset do |x|
      if topology0?(x)
	yield(([[].Set] + x + [self.Set]).Set)
      end
    end
  end

  def tops
    u = Set[]
    each_topology do |t|
      u.push TopologicalSpace.new(self, t)
    end
    u
  end
end

class TopGenerator1 < Set

  def init
    @subset0 = Set[]
    each_subset0 do |s|
      @subset0.push s
    end
    @trivial = TopologicalSpace.new(self, Set[[].Set, self.Set])
  end

  def homeo_representatives0
    ss = @subset0
    tops = Set[@trivial]
    yield @trivial if block_given?

    loop do
      news = []
      ss.each do |s|
	ineffect = []
	tops.each do |o|
	  next if o.top.has? s
	  x = TopologicalSpace.new(self, o.top | [s])
	  x.complete!
	  if tops.exist{|o| o.homeo?(x)} || news.exist{|o| o.homeo?(x)}
	  else
	    yield x if block_given?
	    news.push x
	  end
	end
      end
      if news.empty?
	break
      else
	tops.concat news
      end
    end
    tops
  end

  def homeo_representatives
    ss = @subset0
    tops = Set[@trivial]
    yield @trivial if block_given?
    actives = tops.dup

    while o = actives.shift
      flag = false
      ss.each do |s|
	next if o.top.has? s
	x = TopologicalSpace.new(self, o.top | [s])
	x.complete!
	unless tops.exist{|q| q.homeo?(x)} or actives.exist{|q| q.homeo?(x)}
	  flag = true
	  yield x if block_given?
	  actives.push x
	  tops.push x
	end
      end
      actives.unshift o if flag
    end

    tops
  end
end

if $0 == __FILE__
  m = ARGV.shift.to_i
  n = m % 10
  set = (0...n).to_a.Set

  if m > 10
    top_s = TopGenerator0[* set].tops
#    Set.use_setname
#    top_s.each_with_index{|x, i| x.top.setname i }
    tops = top_s.find_all{|x| x.T0? && x.connected?}.Set
    (tops / :homeo?).each do |x|
      p x.first.top
    end
  else
    tg = TopGenerator1[* set]
    tg.init
    tg.homeo_representatives do |x|
      p x.top if x.T0? && x.connected?
    end
  end
end
