import scala.io.StdIn._
import scala.util.control._

object cf699B {
    def main (args:Array[String]) {
        var line = readLine();
        val ss = line.split(" ");
        val n = ss(0).toInt;
        val m = ss(1).toInt;
        var a = new Array[String](1000 + 5);

        for (i <- 0 until n) {
            a(i) = readLine();
        }

        var r = new Array[Int](1000 + 5);
        for (i <- 0 until n) {
            r(i) = 0;
        }

        var c = new Array[Int](1000 + 5);
        for (i <- 0 until m) {
            c(i) = 0;
        }

        var cnt = 0;

        for (i <- 0 until n) {
            for (j <- 0 until m) {
                if (a(i)(j) == '*') {
                    cnt += 1;
                    r(i) += 1;
                    c(j) += 1;
                }
            }
        }

        var res = false;
        var plcx = 0;
        var plcy = 0;

        var ans = 0;
        for (i <- 0 until n) {
            for (j <- 0 until m) {
                ans = cnt;
                if (a(i)(j) == '*') ans += 1;
                ans -= r(i);
                ans -= c(j);
                if (ans == 0) {
                    res = true;
                    plcx = i + 1;
                    plcy = j + 1;
                }
            }
        }
        if (res == true) {
            println("YES");
            println(plcx + " " + plcy);
        } else {
            println("NO");
        }
    }
}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _699B extends CodeForcesApp {
  override def apply(io: IO) = {import io.{read, write}
    val n, m = read[Int]
    val room = read[Vector, String](n)

    val rowCount, colCount = map[Int] to 0
    var bombs = 0

    for {
      r <- 0 until n
      c <- 0 until m
      if room(r)(c) == '*'
    } {
      rowCount(r) += 1
      colCount(c) += 1
      bombs += 1
    }

    val ans = for {
      r <- 0 until n
      c <- 0 until m
      if rowCount(r) + colCount(c) - (room(r)(c) == '*').to[Int] == bombs
    } yield r -> c

    ans.headOption match {
      case None => write(false.toEnglish)
      case Some((i, j)) => write(true.toEnglish).writeOnNextLine(i + 1, j + 1)
    }
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def in(set: collection.Set[A]): Boolean = set(a)
    def some: Option[A] = Some(a)
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = assuming(t.size == 1)(t.head)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairExtensions[A, B](val p: (A, B)) extends AnyVal {
    def key = p._1
    def value = p._2
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_.key).mapValues(_.value)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_.key).mapValues(_.map(_.value).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def lastKeyOption: Option[K] = m.lastOption.map(_.key)
    def firstKeyOption: Option[K] = m.headOption.map(_.key)
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class MutableMapExtensions[K, V](val m: mutable.Map[K, V]) extends AnyVal {
    def removeLast(): Option[(K, V)] = m.lastOption.map(removeNode)
    def removeFirst(): Option[(K, V)] = m.headOption.map(removeNode)
    private def removeNode(kv: (K, V)): (K, V) = {
      m -= kv.key
      kv
    }
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def deleteAtIndex(i: Int, howMany: Int = 1) = s.patch(i, Nil, howMany)
    def insertAtIndex(i: Int, items: Seq[A]) = s.patch(i, items, 0)
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f).findWithIndex(c)
    def X[B](bs: Iterable[B]): Iterable[(A, B)] = for {a <- s; b <- bs} yield (a, b)
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
    def toEnglish = if(x) "YES" else "NO"
  }
  implicit class IntExtensions(val x: Int) extends AnyVal {
    import java.lang.{Integer => JInt}
    def withHighestOneBit: Int = JInt.highestOneBit(x)
    def withLowestOneBit: Int = JInt.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JInt.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JInt.numberOfTrailingZeros(x)
    def bitCount: Int = JInt.bitCount(x)
    def setLowestBits(n: Int): Int = x | (left(n) - 1)
    def clearLowestBits(n: Int): Int = x & left(n, ~0)
    def setBit(i: Int, set: Boolean): Int = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Int = x | left(i)
    def clearBit(i: Int): Int = x & ~left(i)
    def toggleBit(i: Int): Int = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Int = 1) = assuming(bits >= 0 && bits < JInt.SIZE)(num << bits)
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    import java.lang.{Long => JLong}
    def withHighestOneBitSet: Long = JLong.highestOneBit(x)
    def withLowestOneBitSet: Long = JLong.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JLong.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JLong.numberOfTrailingZeros(x)
    def bitCount: Int = JLong.bitCount(x)
    def setLowestBits(n: Int): Long = x | (left(n) - 1)
    def clearLowestBits(n: Int): Long = x & left(n, ~0L)
    def setBit(i: Int, set: Boolean): Long = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Long = x | left(i)
    def clearBit(i: Int): Long = x & ~left(i)
    def toggleBit(i: Int): Long = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Long = 1L) = assuming(bits >= 0 && bits < JLong.SIZE)(num << bits)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(x, y, if (n.lteq(x, y)) n.one else -n.one)
    def ceilDiv(y: A): A = if (mod(y) == n.zero) x/y else n.one + (x/y)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: => V): Dict[K, V] = using(_ => default)
    def using[V](f: K => V): Dict[K, V] = new mutable.HashMap[K, V]() {
      override def apply(key: K) = getOrElseUpdate(key, f(key))
    }
  }
  def newMultiMap[K, V] = map[K] to mutable.Set.empty[V]
  def memoize[A, B](f: A => B): A ==> B = map[A] using f
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  def assuming[A](cond: => Boolean)(f: => A): A = {require(cond); f}
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) f.some else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  type ==>[A, B] = collection.Map[A, B]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends Iterator[String] with AutoCloseable with Flushable {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered
  val printer = new PrintWriter(out, true)

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    when(tokenizers.nonEmpty)(tokenizers.head)
  }

  def read[A](implicit read: IO.Read[A]): A = read.apply(this)
  def read[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(read).to[C]

  def readTill(delim: String): String = tokenizer().get.nextToken(delim)
  def readTillEndOfLine(): String = readTill("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  def write(obj: Any, more: Any*): this.type = {
    printer.print(obj)
    more foreach {i =>
      printer.print(' ')
      printer.print(i)
    }
    this
  }
  def writeOnNextLine(obj: Any, more: Any*): this.type = {
    printer.println()
    write(obj, more: _*)
    this
  }
  def writeAll(obj: Traversable[Any], separator: String = " "): this.type = write(obj mkString separator)

  override def flush() = printer.flush()
  def close() = {
    flush()
    in.close()
    printer.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r.read[C, A](r.read[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r.read[A], r.read[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r.read[A], r.read[B], r.read[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r.read[A], r.read[B], r.read[C], r.read[D]))
    implicit val boolean                                      : Read[Boolean]      = string map {s =>
      s.toLowerCase match {
        case "yes" | "true" | "1" => true
        case "no" | "false" | "0" => false
        case _ => s.toBoolean
      }
    }
  }
}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _699B extends CodeForcesApp {
  override def apply(io: IO) = {import io.{read, write}
    val n, m = read[Int]
    val room = read[Vector, String](n)

    val rowCount, colCount = map[Int] to 0
    var bombs = 0

    n X m foreach { case (r, c) =>
      if (room(r)(c) == '*') {
        rowCount(r) += 1
        colCount(c) += 1
        bombs += 1
      }
    }

    val ans = n X m find { case (r, c) =>
      rowCount(r) + colCount(c) - (room(r)(c) == '*').to[Int] == bombs
    }

    ans match {
      case None => write(false.toEnglish)
      case Some((i, j)) => write(true.toEnglish).writeOnNextLine(i + 1, j + 1)
    }
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def in(set: collection.Set[A]): Boolean = set(a)
    def some: Option[A] = Some(a)
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = assuming(t.size == 1)(t.head)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
    def X[B](s: Traversable[B]): Iterator[(A, B)] = for {a <- t.toIterator; b <- s} yield (a, b)
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairExtensions[A, B](val p: (A, B)) extends AnyVal {
    def key = p._1
    def value = p._2
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_.key).mapValues(_.value)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_.key).mapValues(_.map(_.value).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def lastKeyOption: Option[K] = m.lastOption.map(_.key)
    def firstKeyOption: Option[K] = m.headOption.map(_.key)
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class MutableMapExtensions[K, V](val m: mutable.Map[K, V]) extends AnyVal {
    def removeLast(): Option[(K, V)] = m.lastOption.map(removeNode)
    def removeFirst(): Option[(K, V)] = m.headOption.map(removeNode)
    private def removeNode(kv: (K, V)): (K, V) = {
      m -= kv.key
      kv
    }
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def deleteAtIndex(i: Int, howMany: Int = 1) = s.patch(i, Nil, howMany)
    def insertAtIndex(i: Int, items: Seq[A]) = s.patch(i, items, 0)
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f).findWithIndex(c)
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
    def toEnglish = if(x) "YES" else "NO"
  }
  implicit class IntExtensions(val x: Int) extends AnyVal {
    import java.lang.{Integer => JInt}
    def withHighestOneBit: Int = JInt.highestOneBit(x)
    def withLowestOneBit: Int = JInt.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JInt.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JInt.numberOfTrailingZeros(x)
    def bitCount: Int = JInt.bitCount(x)
    def setLowestBits(n: Int): Int = x | (left(n) - 1)
    def clearLowestBits(n: Int): Int = x & left(n, ~0)
    def setBit(i: Int, set: Boolean): Int = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Int = x | left(i)
    def clearBit(i: Int): Int = x & ~left(i)
    def toggleBit(i: Int): Int = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Int = 1) = assuming(bits >= 0 && bits < JInt.SIZE)(num << bits)
    def X(y: Int): Iterator[(Int, Int)] = until(x) X until(y)
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    import java.lang.{Long => JLong}
    def withHighestOneBitSet: Long = JLong.highestOneBit(x)
    def withLowestOneBitSet: Long = JLong.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JLong.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JLong.numberOfTrailingZeros(x)
    def bitCount: Int = JLong.bitCount(x)
    def setLowestBits(n: Int): Long = x | (left(n) - 1)
    def clearLowestBits(n: Int): Long = x & left(n, ~0L)
    def setBit(i: Int, set: Boolean): Long = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Long = x | left(i)
    def clearBit(i: Int): Long = x & ~left(i)
    def toggleBit(i: Int): Long = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Long = 1L) = assuming(bits >= 0 && bits < JLong.SIZE)(num << bits)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(x, y, if (n.lteq(x, y)) n.one else -n.one)
    def ceilDiv(y: A): A = if (mod(y) == n.zero) x/y else n.one + (x/y)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: => V): Dict[K, V] = using(_ => default)
    def using[V](f: K => V): Dict[K, V] = new mutable.HashMap[K, V]() {
      override def apply(key: K) = getOrElseUpdate(key, f(key))
    }
  }
  def newMultiMap[K, V] = map[K] to mutable.Set.empty[V]
  def memoize[A, B](f: A => B): A ==> B = map[A] using f
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  def until(until: Int): Range = 0 until until
  def assuming[A](cond: => Boolean)(f: => A): A = {require(cond); f}
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) f.some else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  type ==>[A, B] = collection.Map[A, B]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends Iterator[String] with AutoCloseable with Flushable {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered
  val printer = new PrintWriter(out, true)

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    when(tokenizers.nonEmpty)(tokenizers.head)
  }

  def read[A](implicit read: IO.Read[A]): A = read.apply(this)
  def read[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(read).to[C]

  def readTill(delim: String): String = tokenizer().get.nextToken(delim)
  def readTillEndOfLine(): String = readTill("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  def write(obj: Any, more: Any*): this.type = {
    printer.print(obj)
    more foreach {i =>
      printer.print(' ')
      printer.print(i)
    }
    this
  }
  def writeOnNextLine(obj: Any, more: Any*): this.type = {
    printer.println()
    write(obj, more: _*)
    this
  }
  def writeAll(obj: Traversable[Any], separator: String = " "): this.type = write(obj mkString separator)

  override def flush() = printer.flush()
  def close() = {
    flush()
    in.close()
    printer.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r.read[C, A](r.read[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r.read[A], r.read[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r.read[A], r.read[B], r.read[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r.read[A], r.read[B], r.read[C], r.read[D]))
    implicit val boolean                                      : Read[Boolean]      = string map {s =>
      s.toLowerCase match {
        case "yes" | "true" | "1" => true
        case "no" | "false" | "0" => false
        case _ => s.toBoolean
      }
    }
  }
}

import scala.util.Sorting
import scala.io.StdIn

object App {

  def main(args: Array[String]) {

    val Array(n,m) = StdIn.readLine().split(" ").map(_.toInt)

    var N:Array[Int] = new Array[Int](n)
    var M:Array[Int] = new Array[Int](m)

    var TD = Array.ofDim[Array[Int]](n)
    var sum = 0
    for(i <- 0 to n - 1) {
      TD(i) = StdIn.readLine().toCharArray.map(t=> if(t == '*') 1 else 0);
      TD(i)
        .zipWithIndex
        .foreach((a) => {
            sum+=TD(i)(a._2)
            N(i)+=TD(i)(a._2)
            M(a._2)+=TD(i)(a._2)
        })
    }

    for(i <- 0 to n - 1) {
      for(j <- 0 to m - 1) {
        if(M(j) + N(i) - TD(i)(j) == sum) {
          println("YES")
          println((i+1) + " " + (j+1))
          return
        }
      }
    }
    println("NO")

  }

}

import scala.io._
import java.util.Scanner
import java.io.BufferedReader
import java.io.InputStreamReader
import scala.collection.breakOut

object Main {
    def main(args: Array[String]) {
        val bfReader = new BufferedReader(new InputStreamReader(System.in))
        val scanner = new Scanner(bfReader.readLine())
        val (n, m) = (scanner.nextInt(), scanner.nextInt())
        val a = for (r <- 0 until n; line = bfReader.readLine()) yield line

        def cellVal(ch: Char): Int = if (ch == '*') 1 else 0

        val pr = a.map(chs  => chs.map(cellVal).sum)
        val pc = for (c <- 0 until m) yield a.map(chs => chs(c)).map(cellVal).sum

        val allBombsVal = a.map(chs => chs.map(cellVal).sum).sum
        val validPositions = for (r <- 0 until n; c <- 0 until m if pr(r) + pc(c) - cellVal(a(r)(c)) == allBombsVal) yield (r, c)

        if (validPositions.isEmpty) println("NO")
        else {
            val (r, c) = validPositions(0)
            println(s"YES\n${r + 1} ${c + 1}")
        }
    }
}

import scala.util.control.Breaks._

object main extends App{
  val Array(n, m) = readLine.split(" ").map(_.toInt)
  var area = new Array[String](n)
  var rows = new Array[Int](n)
  var cols = new Array[Int](m)
  var count = 0
  for (i <- 0 until n) {
  	area(i) = readLine
  	rows(i) = area(i).toArray.foldLeft(0)((count: Int, char: Char) => if (char == '*') count + 1 else count)
  	count += rows(i)
  	List.range(0, m).foreach((j: Int) => if (area(i)(j) == '*') cols(j) += 1 )
  }
  val r = () => {
  	var result: Any = "NO";
  	for (i <- 0 until n) {
	  	for (j <- 0 until m) {
	  		val res = rows(i) + cols(j) - (if (area(i)(j) == '*') 1 else 0)
	  		if (res >= count) {
	  			result = Array(i+1, j+1)
	  		}
	  	}
  	}
  	result;
  }
  r() match {
  	case s: String => println(s)
  	case Array(x, y) => {
  		println("YES")
  		println("%d %d".format(x, y))
  	}
  }
}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, m) = in.next().split(' ').map(_.toInt)
  val lines = in.take(n).toList
  val linesBig = lines.indices.filter(i => lines(i).count(_ == '*') > 1).toList
  if (linesBig.length > 1) {
    println("NO")
  }
  else if (linesBig.length == 1) {
    val y = linesBig.head
    val columnsBig = lines
      .indices
      .filter(i => i != y && lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .distinct

    if (columnsBig.length > 1)
      println("NO")
    else if (columnsBig.length == 1) {
      println("YES")

      println(s"${y + 1} ${columnsBig.head + 1}")
    } else {
      println("YES")
      println(s"${y + 1} 1")
    }
  } else {
    val columnsBig = lines
      .indices
      .filter(i => lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .groupBy(i => i)
      .map(i => i._1 -> i._2.length)

    if (columnsBig.size > 2)
      println("NO")
    else if (columnsBig.size == 2) {
      val one = columnsBig.find(_._2 == 1)
      if (one.isEmpty) {
        println("NO")
      } else {
        val y = lines.indices.find(i => lines(i)(one.get._1) == '*').get
        val x = columnsBig.find(i => i._1 != one.get._1).get._1
        println("YES")
        println(s"${y + 1} ${x + 1}")
      }
    } else if (columnsBig.size == 1) {
      println("YES")
      println(s"1 ${columnsBig.head._1 + 1}")
    } else {
      println("YES")
      println("1 1")
    }

  }

}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _699B extends CodeForcesApp {
  override def apply(io: IO) = {import io.{read, write}
    val n, m = read[Int]
    val room = read[Vector, String](n)

    val rowCount, colCount = map[Int] to 0
    var bombs = 0

    until(n, m) foreach { case (r, c) =>
      if (room(r)(c) == '*') {
        rowCount(r) += 1
        colCount(c) += 1
        bombs += 1
      }
    }

    val ans = until(n, m) find { case (r, c) =>
      rowCount(r) + colCount(c) - (room(r)(c) == '*').to[Int] == bombs
    }

    ans match {
      case None => write(false.toEnglish)
      case Some((i, j)) => write(true.toEnglish).writeOnNextLine(i + 1, j + 1)
    }
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def in(set: collection.Set[A]): Boolean = set(a)
    def some: Option[A] = Some(a)
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = assuming(t.size == 1)(t.head)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
    def X[B](s: Traversable[B]): Iterator[(A, B)] = for {a <- t.toIterator; b <- s} yield (a, b)
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairExtensions[A, B](val p: (A, B)) extends AnyVal {
    def key = p._1
    def value = p._2
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_.key).mapValues(_.value)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_.key).mapValues(_.map(_.value).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def lastKeyOption: Option[K] = m.lastOption.map(_.key)
    def firstKeyOption: Option[K] = m.headOption.map(_.key)
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class MutableMapExtensions[K, V](val m: mutable.Map[K, V]) extends AnyVal {
    def removeLast(): Option[(K, V)] = m.lastOption.map(removeNode)
    def removeFirst(): Option[(K, V)] = m.headOption.map(removeNode)
    private def removeNode(kv: (K, V)): (K, V) = {
      m -= kv.key
      kv
    }
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def deleteAtIndex(i: Int, howMany: Int = 1) = s.patch(i, Nil, howMany)
    def insertAtIndex(i: Int, items: Seq[A]) = s.patch(i, items, 0)
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f).findWithIndex(c)
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
    def toEnglish = if(x) "YES" else "NO"
  }
  implicit class IntExtensions(val x: Int) extends AnyVal {
    import java.lang.{Integer => JInt}
    def withHighestOneBit: Int = JInt.highestOneBit(x)
    def withLowestOneBit: Int = JInt.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JInt.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JInt.numberOfTrailingZeros(x)
    def bitCount: Int = JInt.bitCount(x)
    def setLowestBits(n: Int): Int = x | (left(n) - 1)
    def clearLowestBits(n: Int): Int = x & left(n, ~0)
    def setBit(i: Int, set: Boolean): Int = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Int = x | left(i)
    def clearBit(i: Int): Int = x & ~left(i)
    def toggleBit(i: Int): Int = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Int = 1) = assuming(bits >= 0 && bits < JInt.SIZE)(num << bits)
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    import java.lang.{Long => JLong}
    def withHighestOneBitSet: Long = JLong.highestOneBit(x)
    def withLowestOneBitSet: Long = JLong.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JLong.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JLong.numberOfTrailingZeros(x)
    def bitCount: Int = JLong.bitCount(x)
    def setLowestBits(n: Int): Long = x | (left(n) - 1)
    def clearLowestBits(n: Int): Long = x & left(n, ~0L)
    def setBit(i: Int, set: Boolean): Long = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Long = x | left(i)
    def clearBit(i: Int): Long = x & ~left(i)
    def toggleBit(i: Int): Long = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Long = 1L) = assuming(bits >= 0 && bits < JLong.SIZE)(num << bits)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(x, y, if (n.lteq(x, y)) n.one else -n.one)
    def ceilDiv(y: A): A = if (mod(y) == n.zero) x/y else n.one + (x/y)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: => V): Dict[K, V] = using(_ => default)
    def using[V](f: K => V): Dict[K, V] = new mutable.HashMap[K, V]() {
      override def apply(key: K) = getOrElseUpdate(key, f(key))
    }
  }
  def newMultiMap[K, V] = map[K] to mutable.Set.empty[V]
  def memoize[A, B](f: A => B): A ==> B = map[A] using f
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  def until(until: Int): Range = 0 until until
  def until(d1: Int, d2: Int): Iterator[(Int, Int)] = (0 until d1) X (0 until d2)
  def assuming[A](cond: => Boolean)(f: => A): A = {require(cond); f}
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) f.some else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  type ==>[A, B] = collection.Map[A, B]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends Iterator[String] with AutoCloseable with Flushable {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered
  val printer = new PrintWriter(out, true)

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    when(tokenizers.nonEmpty)(tokenizers.head)
  }

  def read[A](implicit read: IO.Read[A]): A = read.apply(this)
  def read[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(read).to[C]

  def readTill(delim: String): String = tokenizer().get.nextToken(delim)
  def readTillEndOfLine(): String = readTill("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  def write(obj: Any, more: Any*): this.type = {
    printer.print(obj)
    more foreach {i =>
      printer.print(' ')
      printer.print(i)
    }
    this
  }
  def writeOnNextLine(obj: Any, more: Any*): this.type = {
    printer.println()
    write(obj, more: _*)
    this
  }
  def writeAll(obj: Traversable[Any], separator: String = " "): this.type = write(obj mkString separator)

  override def flush() = printer.flush()
  def close() = {
    flush()
    in.close()
    printer.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r.read[C, A](r.read[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r.read[A], r.read[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r.read[A], r.read[B], r.read[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r.read[A], r.read[B], r.read[C], r.read[D]))
    implicit val boolean                                      : Read[Boolean]      = string map {s =>
      s.toLowerCase match {
        case "yes" | "true" | "1" => true
        case "no" | "false" | "0" => false
        case _ => s.toBoolean
      }
    }
  }
}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    if (maxValue > 1) {
      map foreach {
        case (key, value) => {
          if (key != maxIndex && value.size > 1) {
            maxValue = 0
          }
        }
      }
    }
    (maxIndex + 1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      if (maxRowValue != 1 && maxColValue != 1) {
        println(maxRowIndex + " " + maxColIndex)
      } else if (maxRowValue == 1 && maxColValue == 1) {
        if (starCount == 1) {
          println(maxRowIndex + " " + maxColIndex)
        } else {
          val row = colList(maxColIndex - 1).get(0)
          var rrow = 0
          rowList foreach {
            case (key, value) => {
              if (key != row && !colList(maxColIndex - 1).contains(key)) {
                rrow = key
              }
            }
          }
          val col = rowList(rrow).get(0)
          var ccol = 0
          colList foreach {
            case (key, value) => {
              if (key != col && !rowList(rrow).contains(key)) {
                ccol = key
              }
            }
          }
          println((rrow + 1) + " " + (ccol + 1))
        }
      } else if (maxColValue != 1) {
        val row = colList(maxColIndex - 1).get(0)
        var rrow = 0
        rowList foreach {
          case (key, value) => {
            if (key != row && !colList(maxColIndex - 1).contains(key)) {
              rrow = key
            }
          }
        }
        println((rrow + 1) + " " + maxColIndex)
      } else {
        val col = rowList(maxRowIndex - 1).get(0)
        var ccol = 0
        colList foreach {
          case (key, value) => {
            if (key != col && !rowList(maxRowIndex - 1).contains(key)) {
              ccol = key
            }
          }
        }
        println(maxRowIndex + " " + (ccol + 1))
      }
    } else {
      println("NO")
    }
  }

  solve()

}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _699B extends CodeForcesApp {
  override def apply(io: IO) = {import io.{read, write}
    val n, m = read[Int]
    val room = read[Vector, String](n)

    val rowCount, colCount = map[Int] to 0
    var bombs = 0

    until(n, m) foreach { case (r, c) =>
      if (room(r)(c) == '*') {
        rowCount(r) += 1
        colCount(c) += 1
        bombs += 1
      }
    }

    val ans = until(n, m) find { case (r, c) =>
      rowCount(r) + colCount(c) - (room(r)(c) == '*').to[Int] == bombs
    }

    ans match {
      case None => write(false.toEnglish)
      case Some((i, j)) => write(true.toEnglish).writeOnNextLine(i + 1, j + 1)
    }
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def in(set: collection.Set[A]): Boolean = set(a)
    def some: Option[A] = Some(a)
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = assuming(t.size == 1)(t.head)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
    def X[B](s: Iterable[B]): Iterator[(A, B)] = for {a <- t.toIterator; b <- s} yield (a, b)
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairExtensions[A, B](val p: (A, B)) extends AnyVal {
    def key = p._1
    def value = p._2
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_.key).mapValues(_.value)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_.key).mapValues(_.map(_.value).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def lastKeyOption: Option[K] = m.lastOption.map(_.key)
    def firstKeyOption: Option[K] = m.headOption.map(_.key)
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class MutableMapExtensions[K, V](val m: mutable.Map[K, V]) extends AnyVal {
    def removeLast(): Option[(K, V)] = m.lastOption.map(removeNode)
    def removeFirst(): Option[(K, V)] = m.headOption.map(removeNode)
    private def removeNode(kv: (K, V)): (K, V) = {
      m -= kv.key
      kv
    }
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def deleteAtIndex(i: Int, howMany: Int = 1) = s.patch(i, Nil, howMany)
    def insertAtIndex(i: Int, items: Seq[A]) = s.patch(i, items, 0)
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f).findWithIndex(c)
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
    def toEnglish = if(x) "YES" else "NO"
  }
  implicit class IntExtensions(val x: Int) extends AnyVal {
    import java.lang.{Integer => JInt}
    def withHighestOneBit: Int = JInt.highestOneBit(x)
    def withLowestOneBit: Int = JInt.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JInt.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JInt.numberOfTrailingZeros(x)
    def bitCount: Int = JInt.bitCount(x)
    def setLowestBits(n: Int): Int = x | (left(n) - 1)
    def clearLowestBits(n: Int): Int = x & left(n, ~0)
    def setBit(i: Int, set: Boolean): Int = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Int = x | left(i)
    def clearBit(i: Int): Int = x & ~left(i)
    def toggleBit(i: Int): Int = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Int = 1) = assuming(bits >= 0 && bits < JInt.SIZE)(num << bits)
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    import java.lang.{Long => JLong}
    def withHighestOneBitSet: Long = JLong.highestOneBit(x)
    def withLowestOneBitSet: Long = JLong.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JLong.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JLong.numberOfTrailingZeros(x)
    def bitCount: Int = JLong.bitCount(x)
    def setLowestBits(n: Int): Long = x | (left(n) - 1)
    def clearLowestBits(n: Int): Long = x & left(n, ~0L)
    def setBit(i: Int, set: Boolean): Long = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Long = x | left(i)
    def clearBit(i: Int): Long = x & ~left(i)
    def toggleBit(i: Int): Long = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Long = 1L) = assuming(bits >= 0 && bits < JLong.SIZE)(num << bits)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(x, y, if (n.lteq(x, y)) n.one else -n.one)
    def ceilDiv(y: A): A = if (mod(y) == n.zero) x/y else n.one + (x/y)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: => V): Dict[K, V] = using(_ => default)
    def using[V](f: K => V): Dict[K, V] = new mutable.HashMap[K, V]() {
      override def apply(key: K) = getOrElseUpdate(key, f(key))
    }
  }
  def newMultiMap[K, V] = map[K] to mutable.Set.empty[V]
  def memoize[A, B](f: A => B): A ==> B = map[A] using f
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  def until(until: Int): Range = 0 until until
  def until(d1: Int, d2: Int): Iterator[(Int, Int)] = (0 until d1) X (0 until d2)
  def assuming[A](cond: => Boolean)(f: => A): A = {require(cond); f}
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) f.some else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  type ==>[A, B] = collection.Map[A, B]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends Iterator[String] with AutoCloseable with Flushable {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered
  val printer = new PrintWriter(out, true)

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    when(tokenizers.nonEmpty)(tokenizers.head)
  }

  def read[A](implicit read: IO.Read[A]): A = read.apply(this)
  def read[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(read).to[C]

  def readTill(delim: String): String = tokenizer().get.nextToken(delim)
  def readTillEndOfLine(): String = readTill("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  def write(obj: Any, more: Any*): this.type = {
    printer.print(obj)
    more foreach {i =>
      printer.print(' ')
      printer.print(i)
    }
    this
  }
  def writeOnNextLine(obj: Any, more: Any*): this.type = {
    printer.println()
    write(obj, more: _*)
    this
  }
  def writeAll(obj: Traversable[Any], separator: String = " "): this.type = write(obj mkString separator)

  override def flush() = printer.flush()
  def close() = {
    flush()
    in.close()
    printer.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r.read[C, A](r.read[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r.read[A], r.read[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r.read[A], r.read[B], r.read[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r.read[A], r.read[B], r.read[C], r.read[D]))
    implicit val boolean                                      : Read[Boolean]      = string map {s =>
      s.toLowerCase match {
        case "yes" | "true" | "1" => true
        case "no" | "false" | "0" => false
        case _ => s.toBoolean
      }
    }
  }
}

import scala.io.StdIn._
import scala.util.control._

object cf699B {
    def main (args:Array[String]) {
        var line = readLine();
        val ss = line.split(" ");
        val n = ss(0).toInt;
        val m = ss(1).toInt;
        var a = new Array[String](1000 + 5);

        for (i <- 0 until n) {
            a(i) = readLine();
        }

        var r = new Array[Int](1000 + 5);
        for (i <- 0 until n) {
            r(i) = 0;
        }

        var c = new Array[Int](1000 + 5);
        for (i <- 0 until m) {
            c(i) = 0;
        }

        var cnt = 0;

        for (i <- 0 until n) {
            for (j <- 0 until m) {
                if (a(i)(j) == '*') {
                    cnt += 1;
                    r(i) += 1;
                    c(j) += 1;
                }
            }
        }

        var res = false;
        var plcx = 0;
        var plcy = 0;

        var ans = 0;
        for (i <- 0 until n) {
            for (j <- 0 until m) {
                ans = cnt;
                if (a(i)(j) == '*') ans += 1;
                ans -= r(i);
                ans -= c(j);
                if (ans == 0) {
                    res = true;
                    plcx = i;
                    plcy = j;
                }
            }
        }
        if (res == true) {
            println("YES");
            println(plcx + 1 + " " + plcy + 1);
        } else {
            println("NO");
        }
    }
}

import scala.io._
import java.util.Scanner
import java.io.BufferedReader
import java.io.InputStreamReader
import scala.collection.breakOut

object Main {
    def main(args: Array[String]) {
        case class Cell(r: Int, c: Int, ch: Char)

        val bfReader = new BufferedReader(new InputStreamReader(System.in))
        val scanner = new Scanner(bfReader.readLine())
        val (n, m) = (scanner.nextInt(), scanner.nextInt())
        val a = for(r <- 0 until n; (ch, c) <- bfReader.readLine().zipWithIndex) yield Cell(r, c, ch)

        def cellVal(c: Cell): Int = c.ch match { case '*' => 1; case '.' => 0 }

        val pr = a.groupBy{ _.r }.map{ case(r, xs) => (r, xs.map(cellVal).sum) }
        val pc = a.groupBy{ _.c }.map{ case(c, xs) => (c, xs.map(cellVal).sum) }

        val allBombsVal = a.map(cellVal).sum
        val validPositions = a.filter(x => x.ch == '*' && pr(x.r) + pc(x.c) - 1 == allBombsVal)

        if (validPositions.isEmpty) println("NO")
        else {
            val x = validPositions(0)
            println(s"YES\n${x.r + 1} ${x.c + 1}")
        }
    }
}

import scala.io._
import java.util.Scanner
import java.io.BufferedReader
import java.io.InputStreamReader
import scala.collection.breakOut

object Main {
    def main(args: Array[String]) {
        case class Cell(r: Int, c: Int, ch: Char)

        val bfReader = new BufferedReader(new InputStreamReader(System.in))
        val scanner = new Scanner(bfReader.readLine())
        val (n, m) = (scanner.nextInt(), scanner.nextInt())
        val a = for(r <- 0 until n; (ch, c) <- bfReader.readLine().zipWithIndex) yield Cell(r, c, ch)

        def cellVal(c: Cell): Int = if (c.ch == "*") 1 else 0

        val pr: Vector[Int] = a.groupBy{ _.r }.map{ case(r, xs) => (r, xs.map(cellVal).sum) }.to[Vector].sorted.map{ case (r, s) => s }
        val pc = a.groupBy{ _.c }.map{ case(c, xs) => (c, xs.map(cellVal).sum) }.to[Vector].sorted.map{ case (c, s) => s }

        val allBombsVal = a.map(cellVal).sum
        val validPositions = a.filter(x => pr(x.r) + pc(x.c) - cellVal(x) == allBombsVal)

        if (validPositions.isEmpty) println("NO")
        else {
            val x = validPositions(0)
            println(s"YES\n${x.r + 1} ${x.c + 1}")
        }
    }
}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, m) = in.next().split(' ').map(_.toInt)
  val lines = in.take(n).toList
  val linesBig = lines.indices.filter(i => lines(i).count(_ == '*') > 1).toList
  if (linesBig.length > 1) {
    println("NO")
  }
  else if (linesBig.length == 1) {
    val y = linesBig.head
    val columnsBig = lines
      .indices
      .filter(i => i != y && lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .distinct

    if (columnsBig.length > 1)
      println("NO")
    else if (columnsBig.length == 1) {
      println("YES")

      println(s"${y + 1} ${columnsBig.head + 1}")
    } else {
      println("YES")
      println(s"${y + 1} 1")
    }
  } else {
    val columnsBig = lines
      .indices
      .filter(i => lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .groupBy(i => i)
      .map(i => i._1 -> i._2.length)

    if (columnsBig.size > 2)
      println("NO")
    else if (columnsBig.size == 2) {
      val one = columnsBig.find(_._2 == 1)
      if (one.isEmpty) {
        println("NO")
      } else {
        val y = lines.indices.find(i => lines(i)(one.get._1) == '*').get
        val x = columnsBig.find(i => i._1 != one.get._1).get._1
        println("YES")
        println(s"${x + 1} ${y + 1}")
      }
    } else if (columnsBig.size == 1) {
      println("YES")
      println(s"1 ${columnsBig.head._1 + 1}")
    } else {
      println("YES")
      println("1 1")
    }

  }

}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, m) = in.next().split(' ').map(_.toInt)
  val lines = in.take(n).toList
  val linesBig = lines.indices.filter(i => lines(i).count(_ == '*') > 1)
  if (linesBig.length > 1) {
    println("NO")
  }
  else if (linesBig.length == 1) {
    val y = linesBig.head
    val columnsBig = lines
      .indices
      .filter(i => i != y && lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .distinct

    if (columnsBig.length > 1)
      println("NO")
    else if (columnsBig.length == 1) {
      println("YES")
      println(s"${columnsBig.head + 1} ${y + 1}")
    } else {
      println("YES")
      println(s"1 ${y + 1}")
    }
  } else {
    val columnsBig = lines
      .indices
      .filter(i => lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .groupBy(i => i)
      .map(i => i._1 -> i._2.length)

    if (columnsBig.size > 2)
      println("NO")
    else if (columnsBig.size == 2) {
      val one = columnsBig.find(_._2 == 1)
      if (one.isEmpty) {
        println("NO")
      } else {
        val y = linesBig.find(i => lines(i)(one.get._1) == '*')
        val x = linesBig.find(_ != one.get).get
        println("YES")
        println(s"$x $y")
      }
    } else if (columnsBig.size == 1) {
      println("YES")
      println(s"1 ${columnsBig.head._1 + 1}")
    } else {
      println("YES")
      println("1 1")
    }

  }

}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, m) = in.next().split(' ').map(_.toInt)
  val lines = in.take(n).toList
  val linesBig = lines.indices.filter(i => lines(i).count(_ == '*') > 1).toList
  if (linesBig.length > 1) {
    println("NO")
  }
  else if (linesBig.length == 1) {
    val y = linesBig.head
    val columnsBig = lines
      .indices
      .filter(i => i != y && lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .distinct

    if (columnsBig.length > 1)
      println("NO")
    else if (columnsBig.length == 1) {
      println("YES")

      println(s"${y + 1} ${columnsBig.head + 1}")
    } else {
      println("YES")
      println(s"${y + 1} 1")
    }
  } else {
    val columnsBig = lines
      .indices
      .filter(i => lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .groupBy(i => i)
      .map(i => i._1 -> i._2.length)

    if (columnsBig.size > 2)
      println("NO")
    else if (columnsBig.size == 2) {
      val one = columnsBig.find(_._2 == 1)
      if (one.isEmpty) {
        println("NO")
      } else {
        val y = lines.indices.find(i => lines(i)(one.get._1) == '*').get
        val x = columnsBig.find(i => i._1 != y).get
        println("YES")
        println(s"$y $x ")
      }
    } else if (columnsBig.size == 1) {
      println("YES")
      println(s"1 ${columnsBig.head._1 + 1}")
    } else {
      println("YES")
      println("1 1")
    }

  }

}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, m) = in.next().split(' ').map(_.toInt)
  val lines = in.take(n).toList
  val linesBig = lines.indices.filter(i => lines(i).count(_ == '*') > 1).toList
  if (linesBig.length > 1) {
    println("NO")
  }
  else if (linesBig.length == 1) {
    val y = linesBig.head
    val columnsBig = lines
      .indices
      .filter(i => i != y && lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .distinct

    if (columnsBig.length > 1)
      println("NO")
    else if (columnsBig.length == 1) {
      println("YES")

      println(s"${y + 1} ${columnsBig.head + 1}")
    } else {
      println("YES")
      println(s"${y + 1} 1")
    }
  } else {
    val columnsBig = lines
      .indices
      .filter(i => lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .groupBy(i => i)
      .map(i => i._1 -> i._2.length)

    if (columnsBig.size > 2)
      println("NO")
    else if (columnsBig.size == 2) {
      val one = columnsBig.find(_._2 == 1)
      if (one.isEmpty) {
        println("NO")
      } else {
        val y = lines.indices.find(i => lines(i)(one.get._1) == '*').get
        val x = columnsBig.find(i => i._1 != y).get._1
        println("YES")
        println(s"${y + 1} ${x + 1}")
      }
    } else if (columnsBig.size == 1) {
      println("YES")
      println(s"1 ${columnsBig.head._1 + 1}")
    } else {
      println("YES")
      println("1 1")
    }

  }

}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, m) = in.next().split(' ').map(_.toInt)
  val lines = in.take(n).toList
  val linesBig = lines.indices.filter(i => lines(i).count(_ == '*') > 1)
  if (linesBig.length > 1) {
    println("NO")
  }
  else if (linesBig.length == 1) {
    val y = linesBig.head
    val columnsBig = lines
      .indices
      .filter(i => i != y && lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .distinct

    if (columnsBig.length > 1)
      println("NO")
    else if (columnsBig.length == 1) {
      println("YES")

      println(s"${y + 1} ${columnsBig.head + 1}")
    } else {
      println("YES")
      println(s"${y + 1} 1")
    }
  } else {
    val columnsBig = lines
      .indices
      .filter(i => lines(i).count(_ == '*') != 0)
      .map(i => lines(i).indexOf('*'))
      .groupBy(i => i)
      .map(i => i._1 -> i._2.length)

    if (columnsBig.size > 2)
      println("NO")
    else if (columnsBig.size == 2) {
      val one = columnsBig.find(_._2 == 1)
      if (one.isEmpty) {
        println("NO")
      } else {
        val y = linesBig.find(i => lines(i)(one.get._1) == '*')
        val x = linesBig.find(_ != one.get).get
        println("YES")
        println(s"$y $x ")
      }
    } else if (columnsBig.size == 1) {
      println("YES")
      println(s"${columnsBig.head._1 + 1} 1")
    } else {
      println("YES")
      println("1 1")
    }

  }

}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    if (maxValue > 1) {
      map foreach {
        case (key, value) => {
          if (key != maxIndex && value.size > 1) {
            maxValue = 0
          }
        }
      }
    }
    (maxIndex + 1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      if (maxRowValue != 1 && maxColValue != 1) {
        println(maxRowIndex + " " + maxColIndex)
      } else if (maxRowValue == 1 && maxColValue == 1) {
        if (starCount == 1) {
          println(maxRowIndex + " " + maxColIndex)
        } else {
          val row = colList(maxColIndex - 1).get(0)
          var rrow = 0
          rowList foreach {
            case (key, value) => {
              if (key != row && !colList(maxColIndex - 1).contains(key)) {
                rrow = key
              }
            }
          }
          val col = rowList(rrow).get(0)
          var ccol = 0
          colList foreach {
            case (key, value) => {
              if (key != col && !rowList(maxRowIndex - 1).contains(key)) {
                ccol = key
              }
            }
          }
          println((rrow + 1) + " " + (ccol + 1))
        }
      } else if (maxColValue != 1) {
        val row = colList(maxColIndex - 1).get(0)
        var rrow = 0
        rowList foreach {
          case (key, value) => {
            if (key != row && !colList(maxColIndex - 1).contains(key)) {
              rrow = key
            }
          }
        }
        println((rrow + 1) + " " + maxColIndex)
      } else {
        val col = rowList(maxRowIndex - 1).get(0)
        var ccol = 0
        colList foreach {
          case (key, value) => {
            if (key != col && !rowList(maxRowIndex - 1).contains(key)) {
              ccol = key
            }
          }
        }
        println(maxRowIndex + " " + (ccol + 1))
      }
    } else {
      println("NO")
    }
  }

  solve()

}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    if (maxValue > 1) {
      map foreach {
        case (key, value) => {
          if (key != maxIndex && value.size > 1) {
            maxValue = 0
          }
        }
      }
    }
    (maxIndex + 1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      if ((maxRowValue == 1 && maxColValue == 1) || (maxRowValue != 1 && maxColValue != 1)) {
        println(maxRowIndex + " " + maxColIndex)
      } else if (maxColValue != 1) {
        var row = colList(maxColIndex-1).get(0)
        rowList foreach {
          case (key, value) => {
            if (key != row) {
              row = key
            }
          }
        }
        println((row + 1) + " " + maxColIndex)
      } else {
        var col = rowList(maxRowIndex-1).get(0)
        colList foreach {
          case (key, value) => {
            if (key != col) {
              col = key
            }
          }
        }
        println(maxRowIndex + " " + (col + 1))
      }
    } else {
      println("NO")
    }
  }

  solve()

}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    if (maxValue > 1) {
      map foreach {
        case (key, value) => {
          if (key != maxIndex && value.size > 1) {
            maxValue = 0
          }
        }
      }
    }
    (maxIndex + 1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      println(maxRowIndex + " " + maxColIndex)

    } else {
      println("NO")
    }
  }

  solve()

}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    if (maxValue > 1) {
      map foreach {
        case (key, value) => {
          if (key != maxIndex && value.size > 1) {
            maxValue = 0
          }
        }
      }
    }
    (maxIndex + 1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      if ((maxRowValue == 1 && maxColValue == 1) || (maxRowValue != 1 && maxColValue != 1)) {
        println(maxRowIndex + " " + maxColIndex)
      } else if (maxColValue != 1) {
        val row = colList(maxColIndex-1).get(0)
        var rrow = 0
        rowList foreach {
          case (key, value) => {
            if (key != row) {
              rrow = key
            }
          }
        }
        println((rrow + 1) + " " + maxColIndex)
      } else {
        val col = rowList(maxRowIndex-1).get(0)
        var ccol = 0
        colList foreach {
          case (key, value) => {
            if (key != col) {
              ccol = key
            }
          }
        }
        println(maxRowIndex + " " + (ccol + 1))
      }
    } else {
      println("NO")
    }
  }

  solve()

}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    if (maxValue > 1) {
      map foreach {
        case (key, value) => {
          if (key != maxIndex && value.size > 1) {
            maxValue = 0
          }
        }
      }
    }
    (maxIndex + 1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      if ((maxRowValue == 1 && maxColValue == 1) || (maxRowValue != 1 && maxColValue != 1)) {
        println(maxRowIndex + " " + maxColIndex)
      } else if (maxColValue != 1) {
        var row = colList(maxColIndex-1).get(0)
        rowList foreach {
          case (key, value) => {
            if (key != row) {
              row = key
            }
          }
        }
        println((row + 1) + " " + maxColIndex)
      } else {
        var col = rowList(maxRowIndex-1).get(0)
        colList foreach {
          case (key, value) => {
            if (key != col) {
              col = key
            }
          }
        }
        println(maxRowValue + " " + (col + 1))
      }
    } else {
      println("NO")
    }
  }

  solve()

}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    (maxIndex+1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      println(maxRowIndex + " " + maxColIndex)
    } else {
      println("NO")
    }
  }

  solve()

}

import java.util

import scala.collection.mutable

/**
 * @author pvasilyev
 * @since 11 Aug 2016
 */
object B699 extends App {

  def max(map: mutable.Map[Int, util.ArrayList[Int]]): (Int, Int) = {
    var maxIndex = 0
    var maxValue = 0
    map foreach {
      case (key, value) => {
        if (value.size() > maxValue) {
          maxValue = value.size()
          maxIndex = key
        }
      }
    }
    if (maxValue > 1) {
      map foreach {
        case (key, value) => {
          if (key != maxIndex && value.size > 1) {
            maxValue = 0
          }
        }
      }
    }
    (maxIndex + 1, maxValue)
  }

  def solve() = {
    val Array(n, m): Array[Int] = scala.io.StdIn.readLine().split(" ").map(_.toInt)
    val maze: Array[Array[Char]] = Array.ofDim[Char](n, m)
    for (i <- 0 until n) {
      maze(i) = scala.io.StdIn.readLine().toCharArray
    }
    val rowList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    val colList: mutable.Map[Int, util.ArrayList[Int]] = mutable.Map.empty
    var starCount = 0
    for (i <- 0 until n) {
      for (j <- 0 until m) {
        if (maze(i)(j) == '*') {
          starCount += 1
          if (!rowList.contains(i)) {
            rowList += (i -> new util.ArrayList[Int]())
          }
          if (!colList.contains(j)) {
            colList += (j -> new util.ArrayList[Int]())
          }
          rowList(i).add(j)
          colList(j).add(i)
        }
      }
    }
    val (maxRowIndex, maxRowValue) = max(rowList)
    val (maxColIndex, maxColValue) = max(colList)

    if (maxRowValue + maxColValue - starCount >= 0) {
      println("YES")
      if (maxRowValue != 1 && maxColValue != 1) {
        println(maxRowIndex + " " + maxColIndex)
      } else if (maxRowValue == 1 && maxColValue == 1) {
        if (starCount == 1) {
          println(maxRowIndex + " " + maxColIndex)
        } else {
          val row = colList(maxColIndex - 1).get(0)
          var rrow = 0
          rowList foreach {
            case (key, value) => {
              if (key != row) {
                rrow = key
              }
            }
          }
          val col = rowList(rrow).get(0)
          var ccol = 0
          colList foreach {
            case (key, value) => {
              if (key != col) {
                ccol = key
              }
            }
          }
          println((rrow + 1) + " " + (ccol + 1))
        }
      } else if (maxColValue != 1) {
        val row = colList(maxColIndex - 1).get(0)
        var rrow = 0
        rowList foreach {
          case (key, value) => {
            if (key != row) {
              rrow = key
            }
          }
        }
        println((rrow + 1) + " " + maxColIndex)
      } else {
        val col = rowList(maxRowIndex - 1).get(0)
        var ccol = 0
        colList foreach {
          case (key, value) => {
            if (key != col) {
              ccol = key
            }
          }
        }
        println(maxRowIndex + " " + (ccol + 1))
      }
    } else {
      println("NO")
    }
  }

  solve()

}

import scala.util.control.Breaks._

object main extends App{
  val Array(n, m) = readLine.split(" ").map(_.toInt)
  var area = new Array[String](n)
  var rows = new Array[Int](n)
  var cols = new Array[Int](m)
  var count = 0
  for (i <- 0 until n) {
  	area(i) = readLine
  	rows(i) = area(i).toArray.foldLeft(0)((count: Int, char: Char) => if (char == '*') count + 1 else count)
  	count += rows(i)
  	List.range(0, m).foreach((j: Int) => if (area(i)(j) == '*') cols(j) += 1 )
  }
  println("Count ", count);
  val r = () => {
  	var result: Any = "NO";
  	for (i <- 0 until n) {
	  	for (j <- 0 until m) {
	  		val res = rows(i) + cols(j)
	  		if (res >= count) {
	  			println("Count rows(i) ", rows(i), "count cols(j)", cols(j))
	  			result = Array(i+1, j+1)
	  		}
	  	}
  	}
  	result;
  }
  r() match {
  	case s: String => println(s)
  	case Array(x, y) => {
  		println("YES")
  		println("%d %d".format(x, y))
  	}
  }
}

import scala.util.control.Breaks._

object main extends App{
  val Array(n, m) = readLine.split(" ").map(_.toInt)
  var area = new Array[String](n)
  var rows = new Array[Int](n)
  var cols = new Array[Int](m)
  var count = 0
  for (i <- 0 until n) {
  	area(i) = readLine
  	rows(i) = area(i).toArray.foldLeft(0)((count: Int, char: Char) => if (char == '*') count + 1 else count)
  	count += rows(i)
  	List.range(0, m).foreach((j: Int) => if (area(i)(j) == '*') cols(j) += 1 )
  }
  val r = () => {
  	var result: Any = "NO";
  	for (i <- 0 until n) {
	  	for (j <- 0 until m) {
	  		val res = rows(i) + cols(j)
	  		if (res >= count) {
	  			result = Array(i+1, j+1)
	  		}
	  	}
  	}
  	result;
  }
  r() match {
  	case s: String => println(s)
  	case Array(x, y) => {
  		println("YES")
  		println("%d %d".format(x, y))
  	}
  }
}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _699B extends CodeForcesApp {
  override def apply(io: IO) = {import io.{read, write}
    val n, m = read[Int]
    val map = read[Vector, String](n)

    val bombs = for {
      r <- 0 until n
      c <- 0 until m
      if map(r)(c) == '*'
    } yield (r, c)

    val ans = if (bombs.length >= n+m) {
      None
    } else if (bombs.isEmpty) {
      Some(0 -> 0)
    } else {
      val rb = bombs.groupBy(_._1) collect {
        case (r, bs) if bs.length > 1 => r
      }

      val rc = bombs.groupBy(_._2) collect {
        case (c, bs) if bs.length > 1 => c
      }

      val (cx, cy) = (rb.headOption getOrElse 0) -> (rc.headOption getOrElse 0)
      when(bombs forall {case (i, j) => cx == i || cy == j}) {
        cx -> cy
      }
    }

    ans.map{case (i, j) => (i+1) -> (j+1)} match {
      case None => write(false.toYesNo)
      case Some((i, j)) =>
        write(true.toYesNo).writeLine().write(i, j)
    }
    io
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def in(set: collection.Set[A]): Boolean = set(a)
    def some: Option[A] = Some(a)
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = assuming(t.size == 1)(t.head)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairExtensions[A, B](val p: (A, B)) extends AnyVal {
    def key = p._1
    def value = p._2
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_.key).mapValues(_.value)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_.key).mapValues(_.map(_.value).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def lastKeyOption: Option[K] = m.lastOption.map(_.key)
    def firstKeyOption: Option[K] = m.headOption.map(_.key)
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class MutableMapExtensions[K, V](val m: mutable.Map[K, V]) extends AnyVal {
    def removeLast(): Option[(K, V)] = m.lastOption.map(removeNode)
    def removeFirst(): Option[(K, V)] = m.headOption.map(removeNode)
    private def removeNode(kv: (K, V)): (K, V) = {
      m -= kv.key
      kv
    }
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def deleteAtIndex(i: Int, howMany: Int = 1) = s.patch(i, Nil, howMany)
    def insertAtIndex(i: Int, items: Seq[A]) = s.patch(i, items, 0)
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f).findWithIndex(c)
    def X[B](bs: Iterable[B]): Iterable[(A, B)] = for {a <- s; b <- bs} yield (a, b)
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
    def toYesNo = if(x) "YES" else "NO"
  }
  implicit class IntExtensions(val x: Int) extends AnyVal {
    import java.lang.{Integer => JInt}
    def withHighestOneBit: Int = JInt.highestOneBit(x)
    def withLowestOneBit: Int = JInt.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JInt.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JInt.numberOfTrailingZeros(x)
    def bitCount: Int = JInt.bitCount(x)
    def setLowestBits(n: Int): Int = x | (left(n) - 1)
    def clearLowestBits(n: Int): Int = x & left(n, ~0)
    def setBit(i: Int, set: Boolean): Int = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Int = x | left(i)
    def clearBit(i: Int): Int = x & ~left(i)
    def toggleBit(i: Int): Int = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Int = 1) = assuming(bits >= 0 && bits < JInt.SIZE)(num << bits)
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    import java.lang.{Long => JLong}
    def withHighestOneBitSet: Long = JLong.highestOneBit(x)
    def withLowestOneBitSet: Long = JLong.lowestOneBit(x)
    def numberOfLeadingZeroes: Int = JLong.numberOfLeadingZeros(x)
    def numberOfTrailingZeroes: Int = JLong.numberOfTrailingZeros(x)
    def bitCount: Int = JLong.bitCount(x)
    def setLowestBits(n: Int): Long = x | (left(n) - 1)
    def clearLowestBits(n: Int): Long = x & left(n, ~0L)
    def setBit(i: Int, set: Boolean): Long = if (set) setBit(i) else clearBit(i)
    def setBit(i: Int): Long = x | left(i)
    def clearBit(i: Int): Long = x & ~left(i)
    def toggleBit(i: Int): Long = x ^ left(i)
    def testBit(i: Int): Boolean = ((x >> i) & 1) == 1
    private def left(bits: Int, num: Long = 1L) = assuming(bits >= 0 && bits < JLong.SIZE)(num << bits)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(x, y, if (n.lteq(x, y)) n.one else -n.one)
    def ceilDiv(y: A): A = if (mod(y) == n.zero) x/y else n.one + (x/y)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: => V): Dict[K, V] = using(_ => default)
    def using[V](f: K => V): Dict[K, V] = new mutable.HashMap[K, V]() {
      override def apply(key: K) = getOrElseUpdate(key, f(key))
    }
  }
  def newMultiMap[K, V] = map[K] to mutable.Set.empty[V]
  def memoize[A, B](f: A => B): A ==> B = map[A] using f
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  def assuming[A](cond: => Boolean)(f: => A): A = {require(cond); f}
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) f.some else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  type ==>[A, B] = collection.Map[A, B]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends Iterator[String] with AutoCloseable with Flushable {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered
  val printer = new PrintWriter(out, true)

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    when(tokenizers.nonEmpty)(tokenizers.head)
  }

  def read[A](implicit read: IO.Read[A]): A = read.apply(this)
  def read[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(read).to[C]

  def readTill(delim: String): String = tokenizer().get.nextToken(delim)
  def readTillEndOfLine(): String = readTill("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  def write(obj: Any, more: Any*): this.type = {
    printer.print(obj)
    more foreach {i =>
      printer.print(' ')
      printer.print(i)
    }
    this
  }
  def writeLine(obj: Any*): this.type = {
    if (obj.isEmpty) printer.println() else obj foreach printer.println
    this
  }
  def writeAll(obj: Traversable[Any], separator: String = " "): this.type = write(obj mkString separator)

  override def flush() = printer.flush()
  def close() = {
    flush()
    in.close()
    printer.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r.read[C, A](r.read[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r.read[A], r.read[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r.read[A], r.read[B], r.read[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r.read[A], r.read[B], r.read[C], r.read[D]))
    implicit val boolean                                      : Read[Boolean]      = string map {s =>
      s.toLowerCase match {
        case "yes" | "true" | "1" => true
        case "no" | "false" | "0" => false
        case _ => s.toBoolean
      }
    }
  }
}