import Foundation
let main: () = {
    let (A, B, H, M) = *listOfDouble()
    let S = 0.0
    let Xa = 0 + A * sin(H * .pi / 6 + M * .pi / 360)
    let Ya = 0 - A * cos(H * .pi / 6 + M * .pi / 360)
    let Xb = 0 + B * sin(M * .pi / 30 + S * .pi / 1800)
    let Yb = 0 - B * cos(M * .pi / 30 + S * .pi / 1800)
    let tX = Xa - Xb
    let tY = Ya - Yb
    let ans = sqrt((tX * tX) + (tY * tY))
    print(ans)

}()

//----------------------------------

let dx = [1, 0, -1, 0] //[1, 0, -1, 0, -1,  1, -1, 1]
let dy = [0, 1, 0, -1] //[0, 1, 0, -1, -1, -1,  1, 1]

@inlinable func gcd(_ a: Int, _ b: Int) -> Int { (b > 0) ? gcd(b, a % b) : a }
@inlinable func lcm(_ a: Int, _ b: Int) -> Int { a / gcd(a, b) * b }

//----------------------------------

infix operator  =~ : ComparisonPrecedence
infix operator !=~ : ComparisonPrecedence
func =~ <T: FixedWidthInteger>(left: T, right: Range<T>) -> Bool { right ~= left }
func !=~ <T: FixedWidthInteger>(left: T, right: Range<T>) -> Bool { !(right ~= left) }
func =~ <T: FixedWidthInteger>(left: T, right: ClosedRange<T>) -> Bool { right ~= left }
func !=~ <T: FixedWidthInteger>(left: T, right: ClosedRange<T>) -> Bool { !(right ~= left) }

func =~ <T: Collection > (left: T.Element, right: T) -> Bool where T.Element : Equatable { right.contains(left) }
func !=~ <T: Collection > (left: T.Element, right: T) -> Bool where T.Element : Equatable { !right.contains(left) }

infix operator /^ : MultiplicationPrecedence
infix operator /^= : AssignmentPrecedence
func /^ <T: FixedWidthInteger>(left: T, right: T) -> T { (left + (right - 1)) / right }
func /^= <T: FixedWidthInteger>(left: inout T, right: T) { left = (left + (right - 1)) / right }

@inlinable func chmax<T: Comparable>(_ m: inout T, _ q: T) { if (m < q) { m = q } }
@inlinable func chmin<T: Comparable>(_ m: inout T, _ q: T) { if (m > q) { m = q } }
@inlinable func chRmax<T: Comparable>(_ m: inout T, _ q: T) -> Bool { if (m < q) { m = q; return true } else { return false } }
@inlinable func chRmin<T: Comparable>(_ m: inout T, _ q: T) -> Bool { if (m > q) { m = q; return true } else { return false } }

prefix operator *
prefix func * <T> (a: [T]) -> (T, T) { (a[0], a[1]) }
prefix func * <T> (a: [T]) -> (T, T, T) { (a[0], a[1], a[2]) }
prefix func * <T> (a: [T]) -> (T, T, T, T) { (a[0], a[1], a[2], a[3]) }
prefix func * <T> (a: [T]) -> (T, T, T, T, T) { (a[0], a[1], a[2], a[3], a[4]) }
prefix func * <T> (a: [T]) -> (T, T, T, T, T, T) { (a[0], a[1], a[2], a[3], a[4], a[5]) }

func printErr(_ str: String, terminator: String = "\n") {
    let s = str + terminator
    FileHandle.standardError.write(s.data(using: .utf8)!)
    FileHandle.standardError.synchronizeFile()
}

@inlinable func next() -> String { readLine()! }
@inlinable func nextInt() -> Int { Int(next())! }
@inlinable func nextDouble() -> Double { Double(next())! }
@inlinable func listOfString() -> [String] { next().split(separator: " ").map(String.init) }
@inlinable func listOfInt() -> [Int] { listOfString().map { Int($0)! } }
@inlinable func listOfInt(_ offset: Int = 0) -> [Int] { listOfString().map { Int($0)! + offset } }
@inlinable func listOfInt(_ offsets: Int ...) -> [Int] { listOfString().enumerated().map { Int($0.element)! + offsets[$0.offset % offsets.count] } }
@inlinable func listOfDouble(_ offset: Double = 0.0) -> [Double] { listOfString().map { Double($0)! + offset } }
@inlinable func listOfDouble(_ offsets: Double ...) -> [Double] { listOfString().enumerated().map { Double($0.element)! + offsets[$0.offset % offsets.count] } }

extension Int {
    init(s: String) { self.init(s)! }
    var isEven: Bool { self.isMultiple(of: 2) }
    var isOdd: Bool { !self.isEven }
    var isTrue: Bool { self != 0 }
    var isFalse: Bool { !self.isTrue }
    var toString: String { String(self) }
    var toChar: Character { Character(UnicodeScalar(UInt8(self))) }
}
func + (left: Int, right: Bool) -> Int { left + (right ? 1 : 0) }
extension Character {
    var asciiCode: Int { Int(self.asciiValue!) }
    var string: String { String(self) }
}
extension String {
    @inlinable subscript (position: Int) -> Character { self[self.index(self.startIndex, offsetBy: position)] }
    @inlinable func repeate(_ times: Int) -> String { String(repeating: self, count: times) }
    //  @inlinable subscript (n: Int) -> String { String(self[self.index(self.startIndex, offsetBy: n)]) }
    //  @inlinable subscript (n: Int) -> Int { Int(self[self.index(self.startIndex, offsetBy: n)].asciiValue!) }
    var toInt: Int { Int(self)! }
}
extension String { // VB like
    @inlinable func _index(_ position: Int) -> String.Index! {
        if !(0 ..< self.count ~= position) { return nil }
        return self.index(self.startIndex, offsetBy: position)
    }
    @inlinable func mid(from index: Int, length: Int) -> String! {
        if let startPosition = self._index(index) {
            if let endPosition = self._index(index + length - 1) {
                return String(self[startPosition...endPosition])
            } else {
                let endPosition = self.index(before: self.endIndex)
                return String(self[startPosition...endPosition])
            }
        }
        return ""
    }
    @inlinable func left(_ length: Int) -> String { String(self.prefix(length)) }
    @inlinable func right(_ length: Int) -> String { String(self.suffix(length)) }
}

extension Dictionary {
    @inlinable mutating func getOrSet(_ key: Key, _ defaultValue: () -> Value) -> Value {
        if let stored = self[key] { return stored }
        else {
            let newValue = defaultValue()
            self[key] = newValue
            return newValue
        }
    }
    @inlinable mutating func getOrElse(_ key: Key, _ defaultValue: () -> Value) -> Value {
        if let stored = self[key] { return stored } else { return defaultValue() }
    }
    @inlinable func containsKey(_ key: Key) -> Bool { self.keys.contains(key) }
}

extension Set {
    static func += (left: inout Set<Element>, right: Element) { left.insert(right) }
    static func -= (left: inout Set<Element>, right: Element) { left.remove(right) }
}

extension Array {
    static func += (left: inout Array<Element>, right: Element) { left.append(right) }
    init(_ size: Int, _ initValue: ((Int) -> Element)) {
        self = [Element]()
        for index in 0 ..< size {
            let value = initValue(index)
            self.append(value)
        }
    }
    init(_ size: Int, _ initValue: (() -> Element)) {
        self = [Element]()
        for _ in 0 ..< size {
            let value = initValue()
            self.append(value)
        }
    }
}
typealias IntArray = Array<Int>
typealias DoubleArray = Array<Double>
typealias BoolArray = Array<Bool>
typealias StringArray = Array<String>

extension Array where Element == Int {
    init(_ size: Int) {
        self = [Element](repeating: 0, count: size)
    }
}
extension Array where Element == Double {
    init(_ size: Int) {
        self = [Element](repeating: 0.0, count: size)
    }
}
extension Array where Element == Bool {
    init(_ size: Int) {
        self = [Element](repeating: false, count: size)
    }
}
extension Array where Element == String {
    init(_ size: Int) {
        self = [Element](repeating: "", count: size)
    }
}

extension Array {
    @inlinable func count(_ predicate: ((Element) -> Bool)) -> Int {
        var cnt = 0; for e in self { if (predicate(e)) { cnt += 1 } }
        return cnt
    }
    @inlinable func groupBy<K>(_ keySelector: (Element) -> K) -> [K : [Element]] {
        var destination = [K : [Element]]()
        for element in self {
            let key = keySelector(element)
            var list = destination.getOrSet(key) { [Element]() }
            list.append(element)
            destination[key] = list
        }
        return destination
    }
    @inlinable func groupByIndexed<K>(_ keySelector: (Element) -> K) -> [K : [Int]] {
        var destination = [K : [Int]]()
        for element in self.enumerated() {
            let key = keySelector(element.element)
            var list = destination.getOrSet(key) { [Int]() }
            list.append(element.offset)
            destination[key] = list
        }
        return destination
    }
}

extension Array {
    func binarySearch(_ element: Element, by compare: (Element, Element) -> Int, fromIndex: Int = 0, toIndex: Int = -1) -> Int {
        var low = fromIndex
        var high = (toIndex == -1) ? self.count - 1 : toIndex - 1
        while (low <= high) {
            let mid = (low + high) >> 1 // safe from overflows
            let midVal = self[mid]
            let cmp = compare(midVal, element)
            if (cmp < 0) { low = mid + 1 }          //-1
            else if (0 < cmp) { high = mid - 1 }    // 1
            else { return mid } // key found        // 0
        }
        return -(low + 1)  // key not found
    }
}
extension Array where Element : Comparable {
    func binarySearch(_ element: Element, fromIndex: Int = 0, toIndex: Int = -1) -> Int {
        var low = fromIndex
        var high = (toIndex == -1) ? self.count - 1 : toIndex - 1
        while (low <= high) {
            let mid = (low + high) >> 1 // safe from overflows
            let midVal = self[mid]
            if (midVal < element) { low = mid + 1 }
            else if (midVal > element) { high = mid - 1 }
            else { return mid } // key found
        }
        return -(low + 1)  // key not found
    }
}

extension Array where Element == Int {
    @inlinable func distinct() -> [Element] {
        var set = Set<Element>(), ary = [Element]()
        for n in self.indices { if !set.contains(self[n]) { ary.append(self[n]); set.insert(self[n]) } }
        return ary
    }
    @inlinable func any(_ predicate: (Element) -> Bool) -> Bool {
        var any = false; for element in self { if predicate(element) { any = true } }
        return any
    }
    @inlinable func all(_ predicate: (Element) -> Bool) -> Bool {
        self.allSatisfy(predicate)
    }
    @inlinable func sum() -> Element { self.reduce(0, +) }
    @inlinable func sum(by predicate: (Element) -> Element) -> Element {
        var sum = 0; for e in self { sum += predicate(e) }
        return sum
    }
    @inlinable func joinToString(_ sepatator: String = " ") -> String { self.map { String($0) }.joined(separator: sepatator) }
}

extension Array where Element == Double {
    @inlinable func sum() -> Element { self.reduce(0.0, +) }
    @inlinable func sum(by predicate: (Element) -> Element) -> Element {
        var sum = 0.0; for e in self { sum += predicate(e) }
        return sum
    }
    @inlinable func joinToString(_ sepatator: String = " ") -> String { self.map { String($0) }.joined(separator: sepatator) }
}
extension Array where Element == String {
    @inlinable func toIntDouble() -> (Int, Double) { (Int(self[0])!, Double(self[1])!) }
    @inlinable func toIntString() -> (Int, String) { (Int(self[0])!, self[1]) }
    @inlinable func toIntIntString() -> (Int, Int, String) { (Int(self[0])!, Int(self[1])!, self[2]) }
}

@inlinable func repeate(_ times1: Int, _ action: () -> Void) {
    for _ in 0 ..< times1 { action() }
}
@inlinable func repeate(_ times1: Int, _ action: (Int) -> Void) {
    for index1 in 0 ..< times1 {
        action(index1)
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ action: (Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            action(index1, index2)
        }
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ times3: Int, _ action: (Int, Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            for index3 in 0 ..< times3 {
                action(index1, index2, index3)
            }
        }
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ times3: Int, _ times4: Int, _ action: (Int, Int, Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            for index3 in 0 ..< times3 {
                for index4 in 0 ..< times4 {
                    action(index1, index2, index3, index4)
                }
            }
        }
    }
}

func measureTimeSeconds(block: (() -> Void)) -> Double {
    let startTime = Date()
    block()
    let duration = -startTime.timeIntervalSinceNow
    return duration
}

extension Array {
    func permutation (_ length: Int) -> [[Element]] {
        if length < 0 || length > self.count {
            return []
        } else if length == 0 {
            return [[]]
        } else {
            var permutations: [[Element]] = []
            let combinations = combination(length)
            for combination in combinations {
                var endArray: [[Element]] = []
                var mutableCombination = combination
                permutations += self.permutationHelper(length, array: &mutableCombination, endArray: &endArray)
            }
            return permutations
        }
    }
    private func permutationHelper(_ n: Int, array: inout [Element], endArray: inout [[Element]]) -> [[Element]] {
        if n == 1 {
            endArray += [array]
        }
        for i in 0 ..< n {
            _ = permutationHelper(n - 1, array: &array, endArray: &endArray)
            let j = n % 2 == 0 ? i : 0
            let temp: Element = array[j]
            array[j] = array[n - 1]
            array[n - 1] = temp
        }
        return endArray
    }
    /**
     - parameter length:
     - returns: Returns all of the combinations in the array of the given length
     */
    func combination (_ length: Int) -> [[Element]] {
        if length < 0 || length > self.count {
            return []
        }
        var indexes: [Int] = (0 ..< length).reduce([]) {$0 + [$1]}
        var combinations: [[Element]] = []
        let offset = self.count - indexes.count
        while true {
            var combination: [Element] = []
            for index in indexes {
                combination.append(self[index])
            }
            combinations.append(combination)
            var i = indexes.count - 1
            while i >= 0 && indexes[i] == i + offset {
                i -= 1
            }
            if i < 0 {
                break
            }
            i += 1
            let start = indexes[i-1] + 1
            for j in (i - 1) ..< indexes.count {
                indexes[j] = start + j - i + 1
            }
        }
        return combinations
    }
    /**
     - parameter length: The length of each permutations
     - returns: All of the permutations of this array of a given length, allowing repeats
     */
    func repeatedPermutation(_ length: Int) -> [[Element]] {
        if length < 1 {
            return []
        }
        var indexes: [[Int]] = []
        indexes.repeatedPermutationHelper([], length: length, arrayLength: self.count, indexes: &indexes)
        return indexes.map({ $0.map({ i in self[i] }) })
    }
    private func repeatedPermutationHelper(_ seed: [Int], length: Int, arrayLength: Int, indexes: inout [[Int]]) {
        if seed.count == length {
            indexes.append(seed)
            return
        }
        for i in (0 ..< arrayLength) {
            var newSeed: [Int] = seed
            newSeed.append(i)
            self.repeatedPermutationHelper(newSeed, length: length, arrayLength: arrayLength, indexes: &indexes)
        }
    }
}


import Foundation

let info = readLine()!.split(separator: " ").map{Double($0)!}
let A = info[0]
let B = info[1]
let H = info[2]
let M = info[3]

let rad = (H * 60  + M) * 5.5 / 180.0 * Double.pi
let C = A * A + B * B - (2 * A * B * cos(rad))
print(sqrt(C))


// : (Colon)

import Foundation

func main() {
    let i = readLine()!.split(separator: " ").map{Double($0)!}

    let (a,b,h,m) = (i[0], i[1], i[2], i[3])
    let pi = Double.pi
    // それぞれの針の角度
    let x = 2 * pi * (h * 60 + m) / (60 * 12)
    let y = 2 * pi * (m) / (60)

    let (ax, ay) = (a * cos(x), a * sin(x))
    let (bx, by) = (b * cos(y), a * sin(y))

    let distance = pow(pow(ax - bx, 2) + pow(ay - by, 2), 0.5)
    print(distance)
}

main()


import Foundation

func readFourInts(separator: String.Element = " ") -> (a: Int, b: Int, c: Int, d: Int) {
    let ints = readLine()!.split(separator: separator).map { Int($0)! }
    return (a: ints[0], b: ints[1], c: ints[2], d: ints[3])
}

func mainC() {
    let (A, B, H, M) = readFourInts()

    let times = H * 60 + M
    let Adgree = (Double(times) * 0.5).truncatingRemainder(dividingBy: 360)
    let Bdgree = (Double(times) * 6).truncatingRemainder(dividingBy: 360)

    let diff = abs(Adgree - Bdgree) > 180 ? abs(Adgree - Bdgree) - 180 : abs(Adgree - Bdgree)

    let result = Double(A * A + B * B) - 2 * Double(A * B) * cos(diff * Double.pi / 180)
    print(result.squareRoot())
}
mainC()


import Foundation

struct Vec2 {
    var x:Double;
    var y:Double;
}

func Distance(a:Vec2, b:Vec2)->Double {
    let v = Vec2(x:a.x - b.x, y:a.y - b.y)
    return sqrt(v.x * v.x + v.y * v.y)
}

func CalcHVec(h:Double, m:Double, length:Double) -> Vec2 {
    let pi2 = Double.pi * 2.0
    let hrad = pi2 * h / 12.0
    let mrad = (pi2 / 12.0) * m / 60.0

    return Vec2(x:cos(hrad + mrad) * length, y:sin(hrad + mrad) * length)
}

func CalcMVec(m:Double, length:Double) -> Vec2 {
    let pi2 = Double.pi * 2.0
    let mrad = pi2 * m / 60.0

    return Vec2(x:cos(mrad) * length, y:sin(mrad) * length)
}

let args = readLine()?.split(separator: " ") ?? []

let a = Double(args[0]) ?? 0  // 時針長さ
let b = Double(args[1]) ?? 0  // 分針長さ
let h = Double(args[2]) ?? 0
let m = Double(args[3]) ?? 0

let hvec = CalcHVec(h: h, m: m, length: a)
let mvec = CalcMVec(m: m, length: b)
let result = Distance(a: hvec, b: mvec)

print(SIMD2<Double>(hvec.x, hvec.y))

print(result)


import * as fs from 'fs';

export function Main(input: string) {
    const [a, b, h, m] = input.split(' ').map(int => parseInt(int));    // ?

    const angleH = 2 * Math.PI * (h + m / 60) / 12;   // ?
    const angleM = 2 * Math.PI * m / 60;  // ?

    const Xh = Math.cos(angleH) * a;    // ?
    const Yh = Math.sin(angleH) * a;    // ?

    const Xm = Math.cos(angleM) * b;    // ?
    const Ym = Math.sin(angleM) * b;    // ?

    let result: any = Math.sqrt((Xh - Xm) ** 2 + (Yh - Ym) ** 2);
    // result = result.toFixed(9);

    //output

    console.log(result);
    return result;
}

// Don't edit this line!
Main(fs.readFileSync("/dev/stdin", "utf8"));


import { readFileSync } from "fs";

const read = () =>
  readFileSync(0, "utf8")
    .split("\n")
    .map((line) => line.split(" "));

const main = (input: string[][]) => {
  const [A, B, H, M] = input[0].map(Number);

  const alpha = ((60 * H + M) / (60 * 12)) * 2 * Math.PI;
  const beta = (M / 60) * 2 * Math.PI;

  return Math.sqrt(A ** 2 + B ** 2 - 2 * A * B * Math.cos(alpha - beta));
};

console.log(main(read()));


import * as fs from 'fs';

const readString = (() => {
  const input = fs.readFileSync(0).toString();
  const words = input.split(/[ \n]/);
  let i = 0;
  return () => words[i++] || '';
})();
const readInt = () => parseInt(readString(), 10);

(function main() {
  const A = readInt();
  const B = readInt();
  const H = readInt();
  const M = readInt();

  const hx = A * Math.sin((H + M/60) / 12 * Math.PI * 2);
  const hy = A * Math.cos((H + M/60) / 12 * Math.PI * 2);

  const mx = B * Math.sin(M / 60 * Math.PI * 2);
  const my = B * Math.cos(M / 60 * Math.PI * 2);

  console.log(Math.sqrt((hx - mx) ** 2 + (hy - my) ** 2));
})();


const lines: string[] = [];
const reader = require("readline").createInterface({
  input: process.stdin,
  output: process.stdout,
});
reader.on("line", function (line: string) {
  lines.push(line);
});

reader.on("close", function () {
  const rule = lines.shift().split(" ").map(Number);
  const long = rule[0];
  const short = rule[1];
  const h = rule[2];
  const m = rule[3];

  let angle = 30 * h - 6 * m;
  if (angle >= 180) angle = 360 - angle;

  let res =
    Math.pow(long, 2) +
    Math.pow(short, 2) -
    2 * long * short * Math.cos(angle * (Math.PI / 180));

  res = Math.sqrt(res);

  console.log(res);
});


n = input()
if n[0]==n[1]==n[2] or n[1]==n[2]==n[3] or (len(set(n))==1):
  print("Yes")
else:
  print("No")


n = str(input())
lst = ['000','111','222','333','444','555','666','777','888','999']
answer = 'No'
if n[:3] in lst:
	answer = 'Yes'
if n[1:] in lst:
	answer = 'Yes'
print(answer)


A=input()
if A[0]==A[1]==A[2] or A[1]==A[2]==A[3]:
  print('Yes')
else:
  print('No')


import bisect,collections,copy,heapq,itertools,math,string
import sys
def I():
    # 1 line 1 int
    return int(sys.stdin.readline().rstrip())
def LI():
    # 1 line n ints
    return list(map(int,sys.stdin.readline().rstrip().split()))
def S():
    # 1 line 1 string
    return sys.stdin.readline().rstrip()
def LS():
    # 1 line n strings
    return list(sys.stdin.readline().rstrip().split())

A = S()

if A[0] == A[1] == A[2] or A[1] == A[2] == A[3]:
   print("Yes")
else
   print("No")


import bisect,collections,copy,heapq,itertools,math,string
import sys
def I():
    # 1 line 1 int
    return int(sys.stdin.readline().rstrip())
def LI():
    # 1 line n ints
    return list(map(int,sys.stdin.readline().rstrip().split()))
def S():
    # 1 line 1 string
    return sys.stdin.readline().rstrip()
def LS():
    # 1 line n strings
    return list(sys.stdin.readline().rstrip().split())

A = S()

if A[0] == A[1] == A[2] or
   A[1] == A[2] == A[3]:
   print("Yes")
else
   print("No")


a=set(input())
if len(a)<=2:
  print('Yes')
else:
  print('No')


    import javax.xml.crypto.Data;
    import java.math.BigDecimal;
    import java.util.*;
    import java.io.*;

    public class Main {

        public static void main(String[] args) throws IOException {

            //入力
            //BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            FastScanner sc = new FastScanner();
            int n = sc.nextInt();

            //出力
            int[] a = new int[4];
            for (int i = 3; i >= 0 ; i--) {
                a[i] = n % 10;
                n /= 10;
            }
            if ((a[0] == a[1] && a[1] == a[2])
                    || (a[1] == a[2] && a[2] == a[3])) System.out.println("Yes");
            else System.out.println("No");
        }

    }

    class FastScanner {
        private final InputStream in = System.in;
        private final byte[] buffer = new byte[1024];
        private int ptr = 0;
        private int buflen = 0;
        private boolean hasNextByte() {
            if (ptr < buflen) {
                return true;
            }else{
                ptr = 0;
                try {
                    buflen = in.read(buffer);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (buflen <= 0) {
                    return false;
                }
            }
            return true;
        }
        private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
        private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
        public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
        public String next() {
            if (!hasNext()) throw new NoSuchElementException();
            StringBuilder sb = new StringBuilder();
            int b = readByte();
            while(isPrintableChar(b)) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }
        public long nextLong() {
            if (!hasNext()) throw new NoSuchElementException();
            long n = 0;
            boolean minus = false;
            int b = readByte();
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            if (b < '0' || '9' < b) {
                throw new NumberFormatException();
            }
            while(true){
                if ('0' <= b && b <= '9') {
                    n *= 10;
                    n += b - '0';
                }else if(b == -1 || !isPrintableChar(b)){
                    return minus ? -n : n;
                }else{
                    throw new NumberFormatException();
                }
                b = readByte();
            }
        }
        public int nextInt() {
            long nl = nextLong();
            if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
            return (int) nl;
        }
        public double nextDouble() { return Double.parseDouble(next());}
    }


import java.util.stream.IntStream;
import java.io.*;
import java.util.*;

public class Main {

    public static void main(String[] args) {
        FastScanner sc = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);

        char[] ch = sc.next().toCharArray();
        final int N = ch.length;
        String ans = "No";

        for (int i = 0; i < N - 2; i++) {
            if (ch[i] == ch[i + 1] && ch[i + 1] == ch[i + 2]) {
                ans = "Yes";
            }
        }

        out.println(ans);

        out.flush();
    }
}
// https://qiita.com/p_shiki37/items/a0f6aac33bf60f5f65e4
class FastScanner {

    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;

    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        } else {
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }

    private int readByte() {
        if (hasNextByte()) {
            return buffer[ptr++];
        } else {
            return -1;
        }
    }

    private static boolean isPrintableChar(int c) {
        return 33 <= c && c <= 126;
    }

    public boolean hasNext() {
        while (hasNextByte() && !isPrintableChar(buffer[ptr])) {
            ptr++;
        }
        return hasNextByte();
    }

    public String next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while (isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    public long nextLong() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while (true) {
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            } else if (b == -1 || !isPrintableChar(b)) {
                return minus ? -n : n;
            } else {
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }

    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) {
            throw new NumberFormatException();
        }
        return (int) nl;
    }

    public double nextDouble() {
        return Double.parseDouble(next());
    }
}


import java.util.*;
import java.io.*;
import java.nio.charset.StandardCharsets;

public class Main {
	public static void main(String[] args) throws IOException {
		InputStreamReader reader = new InputStreamReader(System.in, StandardCharsets.UTF_8);
		BufferedReader in = new BufferedReader(reader);
		String N = in.readLine();
		String subA = N.substring(0, 3);
		String subB = N.substring(1, 4);
		boolean condA = true;
		boolean condB = true;
		for (int i = 1; i < subA.length(); ++i) {
			if (subA.charAt(i - 1) != subA.charAt(i)) {
				condA = false;
				break;
			}
		}
		for (int i = 1; i < subB.length(); ++i) {
			if (subB.charAt(i - 1) != subB.charAt(i)) {
				condB = false;
				break;
			}
		}
		if (condA || condB) {
			System.out.println("Yes");
		} else {
			System.out.println("No");
		}

	}
}


import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		Scanner stdIn = new Scanner(System.in);

		String X = stdIn.next();
		String Y = stdIn.next();

		if(X.charAt(0) > Y.charAt(0))
		{
			System.out.println(">");
		}
		else if(X.charAt(0) < Y.charAt(0))
		{
			System.out.println("<");
		}
		else
		{
			System.out.println("=");
		}

	}

}


import java.util.*;
// warm-up
public class Main {

	static void solve() {
		Scanner sc = new Scanner(System.in);
		int[] c = new int[256];
		boolean ok = false;
		for (char ch : sc.next().toCharArray()) if (++c[ch]>=3) ok=true;
		System.out.println(ok ? "Yes" : "No");
		sc.close();
	}

	public static void main(String args[]) {
		solve();
	}

}


import java.util.*;
// warm-up
public class Main {

	static void solve() {
		Scanner sc = new Scanner(System.in);
		int[] c = new int[256];
		boolean ok = false;
		for (char ch : sc.next().toCharArray()) if (++c[ch]==3) ok=true;
		System.out.println(ok ? "Yes" : "No");
		sc.close();
	}

	public static void main(String args[]) {
		solve();
	}

}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
using namespace std;
int n;
char a[10];

int main(){
	scanf("%s", a);
	bool flag = false;
	if(a[0] == a[1] && a[1] == a[2]) flag = true;
	if(a[1] == a[2] && a[2] == a[3]) flag = true;
	if(flag) printf("Yes\n");
	else printf("No\n");
	return 0;
}


#include <stdio.h>
int main()
{
	int n,a,b,c,d;
	scanf("%d",&n);
	a=n/1000;
	b=n%1000/100;
	c=n%100/10;
	d=n%10;
	if((a==b&&b==c)||(b==c&&c==d))
	printf("Yes\n");
	else
	printf("No\n");
	return 0;
}


#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
	int a, b, c, d, e;
	while(~scanf("%d",&e))
		{
		a = e/1000;
		b = (e - a*1000)/100;
		c = (e - a*1000 - b*100)/10;
		d = (e - a*1000 - b*100 - c*10);
		if((a == b && b == c) || (b == c && c == d))
			printf("Yes\n");
	    else
	    	printf("No\n");
		}
}


#include <bits/stdc++.h>
#include <boost/multiprecision/cpp_int.hpp>

#define rep(i,a,b) for(ll i=a;i<b;i++)
#define rrep(i,b,a) for(int i=b;i>=a;i--)
#define fori(a) for(auto i : a )
#define all(a) begin(a), end(a)
#define set(a,b) memset(a,b,sizeof(a))
#define sz(a) a.size()
double pi=acos(-1);
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PF push_front //deque
// #define mp make_pair
#define pq priority_queue
const ll mod=1000000007;
#define f first
#define s second
#define pii pair< ll, ll >
#define vi vector<int>
#define vpii vector<pii>
#define debug(v) for(auto i:v) cout<<i<<" ";
#define tc int t; cin >> t; while(t--)

using namespace boost::multiprecision;
using namespace std;
void optimizeIO(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
}

const int N=1000005;
ll fact[N],invfact[N];
ll power(ll x,ll y){
  if(y<=0) return 1LL;
  ll z=power(x,y/2);
  if(y%2) return (((z*z)%mod)*x)%mod;
  return (z*z)%mod;
}

void pre(){
  fact[0]=invfact[0]=invfact[1]=fact[1]=1;
  rep(i,2,N) fact[i]=(i*fact[i-1])%mod;
  rep(i,2,N) invfact[i]=(invfact[i-1]*power(i,mod-2))%mod;
}
ll nCr(ll n,ll k){ return (((fact[n]*invfact[n-k])%mod)*invfact[k])%mod; }

const int N1=1e6+1;
vector<int> isprime(N1,1),prime;
void seive(){
  rep(i,2,sqrt(N1)+1){
      if(isprime[i]){
        for(int j=i*i;j<N1;j+=i) isprime[j]=0;
        prime.pb(i);
      }
  }
  rep(i,sqrt(N1)+1,N1) if(isprime[i]) prime.pb(i);
}

struct dsu {
    vector<int> par, rank;
    dsu(int n): par(n+1), rank(n+1) {
        for (int i = 0; i <= n; i++) {
            par[i] = i;
            rank[i]= 1;
        }
    }
    int root(int a) {
        if (a == par[a]) return a;
        return par[a] = root(par[a]);
    }
    void merge(int a, int b) {
        a = root(a);
        b = root(b);
        if (a == b) return;
        if (rank[a] > rank[b]) swap(a, b);
        par[b] = a;
    }
    set<int> parent(int n){
        set<int> s;
        for(int i=1;i<=n;i++){
            s.insert(root(i));
        }
        return s;
    }
};

void solve(){
  string s;
  cin>>s;
  if((s[0]==s[1] && s[1]==s[2]) ||(s[1]==s[2] && s[2]==s[3])) cout<<"Yes";
  else cout<<"NO";
}

int main(){
    optimizeIO();
    int r=1;
    {solve();}
}


#include <bits/stdc++.h>
using namespace std;

int main() { string d;
  cin >> d;
  if(d.at(0)==d.at(1) && d.at(1)==d.at(2)){
    cout << "Yes" << endl;
  } else if (d.at(0)==d.at(1) && d.at(1)==d.at(3)){
    cout << "Yes" << endl;
  } else if (d.at(0)==d.at(2) && d.at(2)==d.at(3)){
    cout << "Yes" << endl;
  } else if (d.at(1)==d.at(2) && d.at(2)==d.at(3)){
    cout << "Yes" << endl;
  }
  else{
    cout << "No" << endl;
  }
}


#include <bits/stdc++.h>
using namespace std;

int main() { string d;
  cin >> d;
  if(d.at(1)==d.at(2) && d.at(2)==d.at(3)){
    cout << "Yes" << endl;
  } else if (d.at(1)==d.at(2) && d.at(2)==d.at(4)){
    cout << "Yes" << endl;
  } else if (d.at(1)==d.at(3) && d.at(3)==d.at(4)){
    cout << "Yes" << endl;
  } else if (d.at(2)==d.at(3) && d.at(3)==d.at(4)){
    cout << "Yes" << endl;
  }
  else{
    cout << "No" << endl;
  }
}


#include <stdio.h>

int main() {
	char n[256];
	scanf("%s", &n);
	if ((n[0] == n[1] && n[1] == n[2]) || (n[1] == n[2] && n[2] == n[3])) printf("Yes");
	else printf("No");
	return 0;
}


#include <stdio.h>
#include <string.h>

int main(void){
  int a, i;
  int b[4] = {0};
  scanf("%d",&a);
  for(i=0;i<4;i++){
    b[i] = a % 10;
    a /= 10;
  }
  for(i=0;i<3;i++){
    if(b[i] == b[i+1] && b[i] == b[i+2]){
      printf("Yes\n");
      return 0;
    }
  }

  printf("No\n");
  return 0;
}


#include<stdio.h>
int main()
{
	int i,a,b,c,n,nmax;
	scanf("%d",&a);
	n=1;
	nmax=1;
	b=a/1000;
	a=a%1000;
	for(i=100;i>0;i/=10){
		c=a/i;
		a=a%i;
		if(b==c){
			n++;
		}else{
			if(n<3){
				n=1;
			}
		}
		b=c;
	}
	if(n>=3){
		printf("Yes\n");
	}else{
		printf("No\n");
	}
}


#include <stdio.h>

int main() {
	int number, one, two, three, four;

	scanf("%d", &number);

	one = number % 10;
	two = number % 100 - one;
	three = number % 1000 - one - two;
	four = number - one - two - three;

	two /= 10;
	three /= 100;
	four /= 1000;

	if (one == two) {
		if (one == three)
			printf("Yes");
	}
	if (two == three) {
		if (two == four)
			printf("Yes");
	}
	else
		printf("No");

	return 0;
}


#include <stdio.h>

int main() {
	int number, one, two, three, four;

	//scanf("%d", &number);
	number = 2122;

	one = number % 10;
	two = number % 100 - one;
	three = number % 1000 - one - two;
	four = number - one - two - three;

	two /= 10;
	three /= 100;
	four /= 1000;

	if (one == two) {
		if (one == three)
			printf("Yes");
	}
	if (two == three) {
		if (two == four)
			printf("Yes");
	}
	else
		printf("No");

	return 0;
}


function Main(input) {
  input = input.trim()
  input = input.split("").map(Number);
  if(input[1]==input[2]&&(input[0]==input[1]||input[2]==input[3])) console.log("Yes")
  else console.log("No")
}Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function main(input) {
  var N = input[0];
  console.log(N.match(/([0-9])\1\1/)?"Yes":"No");
}
main(require('fs').readFileSync('/dev/stdin', 'utf8').trim().split("\n"))


function Main(input) {
	input = input.split("\n");
	var n = input[0];
	var s = "No";
	if(n[1]==n[2]){
	    if(n[0]==n[1]||n[2]==n[3])s = "Yes";
	}
	console.log('%s',s);
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function main(input) {
  input = input.trim();
  const a = input.split('');

  console.log((Array.from(new Set(a)).length)==2?'Yes':'No');
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


function main(input) {
  //input = input.trim();
  const a = input.split('');

  console.log((Array.from(new Set(a)).length)==2?'Yes':'No');
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


function main(input) {
  input = input.trim();
  const a = input.split(",");
  console.log((Array.from(new Set(a)).length)==2?'Yes':'No');
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


package main

import (
	"fmt"
)

func main() {
	var s string
	fmt.Scan(&s)
	if s[0] == s[1] && s[1] == s[2] && s[0] == s[2] || s[1] == s[2] && s[2] == s[3] && s[1] == s[3] {
		fmt.Println("Yes")
	} else {
		fmt.Println("No")
	}
}


package main

import "fmt"

func main() {
	var n string
	fmt.Scan(&n)

	cnt := 0
	gd := false
	for i := range n[:len(n)-1] {
		if n[i] == n[i+1] {
			cnt++
			if cnt >= 2 {
				gd = true
			}
		} else {
			cnt = 0
		}
	}
	if gd {
		fmt.Println("Yes")
	} else {
		fmt.Println("No")
	}
}


package main

import "fmt"

func main() {
	var N string
	fmt.Scan(&N)

	if N[0] == N[1] {
		if N[1] == N[2] {
			fmt.Println("Yes")
		} else {
			fmt.Println("No")
		}
	} else {
		if N[1] == N[2] {
			if N[2] == N[3] {
				fmt.Println("Yes")
			} else {
				fmt.Println("No")
			}
		} else {
			fmt.Println("No")
		}
	}
}


package main

import "fmt"

func main() {
	// Code for A - Good Integer
	var S string
	fmt.Scanf("%s", &S)

	if (S[0] == S[1] && S[1] == S[2]) || (S[2] == S[3] && S[3] == S[4]) {
		fmt.Println("Yes")
	} else {
		fmt.Println("No")
	}
}


package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
	"sort"
	"strconv"
)

const (
	initialBufSize = 1e4
	maxBufSize     = 1e6 + 7
)

var buf []byte = make([]byte, maxBufSize)
var sc = bufio.NewScanner(os.Stdin)

func init() {
	sc.Split(bufio.ScanWords)
	sc.Buffer(buf, maxBufSize)
}

func main() {
	N := nextLine()
	cnt := make(map[rune]int)
	for _, v := range N {
		cnt[v]++
	}
	for _, v := range cnt {
		if v >= 3 {
			fmt.Println("Yes")
			return
		}
	}
	fmt.Println("No")
}

func nextLine() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func abs(a int) int {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

func pow(p, q int) int {
	res := p
	if q == 0 {
		return 1
	}
	for i := 0; i < q-1; i++ {
		res *= p
	}
	return res
}

func MinOf(vars ...int) int {
	min := vars[0]
	for _, i := range vars {
		if min > i {
			min = i
		}
	}
	return min
}

func MaxOf(vars ...int) int {
	max := vars[0]
	for _, i := range vars {
		if max < i {
			max = i
		}
	}
	return max
}

func gcdof2numbers(a int, b int) int {
	if b == 0 {
		return a
	}
	return gcdof2numbers(b, a%b)
}

func lcmof2numbers(a int, b int) int {
	return a / gcdof2numbers(a, b) * b
}

// マイナスの場合は考慮していない
func fuctorial(a int) int {
	if a == 1 || a == 0 {
		return 1
	} else {
		return fuctorial(a-1) * a
	}
}

func NextPermutation(x sort.Interface) bool {
	n := x.Len() - 1
	if n < 1 {
		return false
	}
	j := n - 1
	for ; !x.Less(j, j+1); j-- {
		if j == 0 {
			return false
		}
	}
	l := n
	for !x.Less(j, l) {
		l--
	}
	x.Swap(j, l)
	for k, l := j+1, n; k < l; {
		x.Swap(k, l)
		k++
		l--
	}
	return true
}

// 素因数分解したmapを返す
func primeFuctorize(n int) map[int]int {
	pf := map[int]int{}
	for i := 2; i*i <= n; i++ {
		for n%i == 0 {
			pf[i]++
			n /= i
		}
	}
	if n != 1 {
		pf[n]++
	}
	return pf
}

// ここから拝借
// https://shoman.hatenablog.com/entry/2020/02/25/185456
// Stackは[]intのエイリアス
type Stack []int

// Push adds an element
func (s *Stack) Push(v int) {
	*s = append(*s, v)
}

// Pop removes the top element and return it
func (s *Stack) Pop() (int, error) {
	if s.Empty() {
		return 0, fmt.Errorf("stack is empty")
	}

	v := (*s)[len(*s)-1]
	*s = (*s)[:len(*s)-1]
	return v, nil
}

// Peek returns the top value
func (s *Stack) Peek() (int, error) {
	if s.Empty() {
		return 0, fmt.Errorf("stack is empty")
	}

	return (*s)[len(*s)-1], nil
}

// Size returns the length of stack
func (s *Stack) Size() int {
	return len(*s)
}

// Empty returns true when stack is empty
func (s *Stack) Empty() bool {
	return s.Size() == 0
}

// NewStack generates stack
func NewStack() *Stack {
	s := new(Stack)
	return s
}

// golangの公式サンプルより
// https://xn--go-hh0g6u.com/pkg/container/heap/#example__intHeap
// IntHeap は，整数の最小ヒープです。
type IntHeap []int

func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x interface{}) {
	// Push と Pop はポインタレシーバを使っています。
	// なぜなら，スライスの中身だけでなく，スライスの長さも変更するからです。
	*h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

// この例では IntHeap にいくつかの整数を挿入しています。そして，最小値をチェックしてから，
// 優先度順に取り除いています。
func Example_intHeap() {
	h := &IntHeap{2, 1, 5}
	heap.Init(h)
	heap.Push(h, 3)
	fmt.Printf("minimum: %d\n", (*h)[0])
	for h.Len() > 0 {
		fmt.Printf("%d ", heap.Pop(h))
	}
	// Output:
	// minimum: 1
	// 1 2 3 5
}

// golangの公式サンプルより
// https://xn--go-hh0g6u.com/pkg/container/heap/#example__priorityQueue

// Item は，優先キューで管理する項目です。
type Item struct {
	value    string // 値。任意です。
	priority int    // キューにおける優先度
	// index は heap.Interface メソッドで更新されます。
	index int // ヒープにおけるインデックス
}

// PriorityQueue は heap.Interface を実装し，Item のリストを保持します。
type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
	// Pop が最小ではなく最大の優先度を持つ項目を返して欲しいので，ここでは > を使っています。
	return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
	pq[i].index = i
	pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
	n := len(*pq)
	item := x.(*Item)
	item.index = n
	*pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	old[n-1] = nil  // メモリリークを避ける
	item.index = -1 // 安全のため
	*pq = old[0 : n-1]
	return item
}

// update はキューの Item の優先度と値を更新します。
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
	item.value = value
	item.priority = priority
	heap.Fix(pq, item.index)
}


package main

import (
	"fmt"
)

func main() {
	var a, b, c, d int
	fmt.Scanf("%d%d%d%d", &a, &b, &c, &d)
	if (a == b && b == c) || (b == c && c == d) {
		fmt.Printf("%s", "Yes")
	} else {
		fmt.Printf("%d", "No")
	}
}


puts /(\d)\1\1/ =~ gets ? "Yes" : "No"


n =  gets.to_s
puts ((n[0] == n[1] && n[1] == n[2] )||( n[1] == n[2] && n[2] == n[3])) ? "Yes" : "No"


n = readline.split("").map(&:to_i)
puts (n[0] == n[1] && n[1] == n[2]) || (n[1] == n[2] && n[2] == n[3]) ? "Yes" : "No"


puts /[0-9]{3}/.match(gets) ? :Yes: :No


n = gets().chomp.split('')

cnt = 1
n.each_with_index do |chr, i|
  next if i == 0
  if chr == n[i - 1]
    cnt += 1
    break if cnt >= 3
  else
    cnt = 0
  end
end

puts cnt >= 3 ? 'Yes' : 'No'


n = gets().chomp.split('')

cnt = 1
n.each_with_index do |chr, i|
  next if i == 0
  if chr == n[i - 1]
    cnt += 1
  else
    cnt = 0
  end
end

puts cnt >= 3 ? 'Yes' : 'No'


use std::io;

fn procon_read<T: std::str::FromStr>() ->  Vec<T> {
	let mut buf = String::new();
	io::stdin().read_line(&mut buf).expect("");
	let iter = buf.split_whitespace();
	let mut v: Vec<T> = Vec::new();
	for i in iter {
		v.push(i.parse().ok().unwrap());
	}
	v
}

fn main() {
	let v:Vec<i32> = procon_read();
	let n = v[0];
	let s:Vec<char> = n.to_string().chars().collect();
	if s[0] == s[1] && s[1] == s[2] {
		println!("Yes");
	}else if s[1] == s[2] && s[1] == s[3] {
		println!("Yes");
	}else{
		println!("No");
	}
}


use std::str::FromStr;
use std::fmt::Debug;
use std::cmp;
#[allow(dead_code)]
fn read_as_vec<T>() -> Vec<T>
where T: FromStr, <T as FromStr>::Err : Debug{
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().split_whitespace().map(|c| T::from_str(c).unwrap()).collect()

}

#[allow(dead_code)]
fn read_as_string() -> String{
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().to_string()
}

fn main(){
    let mut n: Vec<char> = read_as_string().chars().collect::<Vec<char>>();
    //n.dedup();
    if (n[0] == n[1] && n[1] == n[2]) || (n[1] == n[2] && n[2] == n[3]){
        println!("Yes");
    }else{
        println!("No");
    }
    /*
    if n.len() < 3{
        println!("Yes");
    }else{
        println!("No");
    }
    */
}


fn main() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    if  s.chars().nth(0) == s.chars().nth(1) && s.chars().nth(1) == s.chars().nth(2) ||
        s.chars().nth(1) == s.chars().nth(2) && s.chars().nth(2) == s.chars().nth(3) {
        println!("Yes");
    }
    else {
        println!("No");
    }

}


use proconio::{input, fastout};
use proconio::marker::{Chars};
use proconio::marker::Usize1;
use std::cmp::*;

macro_rules! debug {
      ($($a:expr),*) => {
          eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
    }
}

#[fastout]
fn main() {
    input!{
        n: Chars,
    }

    if n[0]==n[1] || n[1]==n[2] || n[2]==n[3] {
        println!("Yes");
    } else {
        println!("No");
    }

}


use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {n: String};
    let n: String = n;

    let n1 = &n[0..2].parse().unwrap();
    let n2 = &n[1..3].parse().unwrap();

    if n1 % 111 == 0 || n2 % 111 == 0 {
        println!("Yes")
    } else {
        println!("No")
    }
}